From 11b6ee72e134123ecc80289a7063896f404a9541 Mon Sep 17 00:00:00 2001 From: Anush Nadathur Date: Wed, 13 Nov 2024 13:14:52 -0800 Subject: [PATCH 001/219] [Darwin] API to list all network commissioning features supported by an MTRDevice (#36479) * [Darwin] API to list all network commissioning features supported by an MTRDevice - Expose the network commissioning feature bitset as API to know what transports are supported by the device. * Code review comments * Code review comments * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/darwin/Framework/CHIP/MTRDevice.h | 6 ++++++ src/darwin/Framework/CHIP/MTRDevice_Concrete.mm | 6 ++++++ src/darwin/Framework/CHIP/MTRDevice_XPC.mm | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/src/darwin/Framework/CHIP/MTRDevice.h b/src/darwin/Framework/CHIP/MTRDevice.h index 16df47b12d..247223cbe4 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.h +++ b/src/darwin/Framework/CHIP/MTRDevice.h @@ -17,6 +17,7 @@ #import #import +#import #import #import @@ -122,6 +123,11 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) */ @property (nonatomic, readonly, nullable, copy) NSNumber * productID MTR_NEWLY_AVAILABLE; +/** + * Network commissioning features supported by the device. + */ +@property (nonatomic, readonly) MTRNetworkCommissioningFeature networkCommissioningFeatures MTR_NEWLY_AVAILABLE; + /** * Set the delegate to receive asynchronous callbacks about the device. * diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 091d50a5d8..9169507634 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -514,6 +514,12 @@ - (nullable NSNumber *)productID return [_pid copy]; } +- (MTRNetworkCommissioningFeature)networkCommissioningFeatures +{ + std::lock_guard lock(_descriptionLock); + return [_allNetworkFeatures unsignedIntValue]; +} + - (void)_notifyDelegateOfPrivateInternalPropertiesChanges { os_unfair_lock_assert_owner(&self->_lock); diff --git a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm index b5fea425fa..b500633602 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm @@ -141,6 +141,11 @@ - (nullable NSNumber *)productID return [[self._internalState objectForKey:kMTRDeviceInternalPropertyKeyProductID] copy]; } +- (MTRNetworkCommissioningFeature)networkCommissioningFeatures +{ + return [[self._internalState objectForKey:kMTRDeviceInternalPropertyNetworkFeatures] unsignedIntValue]; +} + #pragma mark - Client Callbacks (MTRDeviceDelegate) // required methods for MTRDeviceDelegates From 39e83c96ef2fbdf628e9a33e77ae51dc56eadeee Mon Sep 17 00:00:00 2001 From: Pradip De Date: Wed, 13 Nov 2024 22:11:35 +0000 Subject: [PATCH 002/219] Removal of 2 redundant attributes in CameraAVStreamMgmt cluster. (#36478) SDK update for corresponding Spec change. Remove the CurrentSnapshotConfig and CurrentVideoCodecs as they are captured by the Allocated Video and Snapshot stream attributes. Also, fix a field name in the Snapshotstream allocation command. Run ZAP regen for the corresponding changes. --- .../camera-av-stream-management-cluster.xml | 72 ++- .../zcl/zcl-with-test-extensions.json | 1 - src/app/zap-templates/zcl/zcl.json | 1 - .../data_model/controller-clusters.matter | 58 ++- .../chip/devicecontroller/ChipClusters.java | 137 ++---- .../devicecontroller/ClusterIDMapping.java | 58 ++- .../devicecontroller/ClusterInfoMapping.java | 48 +- .../devicecontroller/ClusterReadMapping.java | 11 - .../CameraAvStreamManagementCluster.kt | 416 ++++-------------- .../CHIPAttributeTLVValueDecoder.cpp | 117 ----- .../python/chip/clusters/CHIPClusters.py | 109 ++--- .../python/chip/clusters/Objects.py | 148 +++---- .../MTRAttributeSpecifiedCheck.mm | 6 - .../MTRAttributeTLVValueDecoder.mm | 42 -- .../CHIP/zap-generated/MTRBaseClusters.h | 14 - .../CHIP/zap-generated/MTRBaseClusters.mm | 121 ----- .../CHIP/zap-generated/MTRClusterConstants.h | 56 ++- .../CHIP/zap-generated/MTRClusterNames.mm | 8 - .../CHIP/zap-generated/MTRClusters.h | 6 - .../CHIP/zap-generated/MTRClusters.mm | 21 - .../zap-generated/MTRCommandPayloadsObjc.h | 2 +- .../zap-generated/MTRCommandPayloadsObjc.mm | 8 +- .../zap-generated/cluster-objects.cpp | 10 +- .../zap-generated/cluster-objects.h | 33 +- .../app-common/zap-generated/ids/Attributes.h | 62 ++- .../zap-generated/cluster/Commands.h | 72 ++- .../cluster/logging/DataModelLogger.cpp | 10 - .../cluster/logging/EntryToText.cpp | 4 - .../zap-generated/cluster/Commands.h | 291 ++---------- 29 files changed, 423 insertions(+), 1519 deletions(-) diff --git a/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml index 24c66bcc7a..516fe8753a 100644 --- a/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/camera-av-stream-management-cluster.xml @@ -18,7 +18,7 @@ limitations under the License. XML generated by Alchemy; DO NOT EDIT. Source: src/app_clusters/CameraAVStreamManagement.adoc Parameters: in-progress -Git: 1.3-3824-g29c49ca54 +Git: 1.3-3830-g1f08d6f40 --> @@ -239,62 +239,48 @@ Git: 1.3-3824-g29c49ca54 - - CurrentVideoCodecs - - - - - - CurrentSnapshotConfig - - - - - FabricsUsingCamera - + FabricsUsingCamera + AllocatedVideoStreams - + AllocatedAudioStreams - + AllocatedSnapshotStreams - + RankedVideoStreamPrioritiesList - - - + SoftRecordingPrivacyModeEnabled - + SoftLivestreamPrivacyModeEnabled - + HardPrivacyModeOn - + NightVision @@ -305,7 +291,7 @@ Git: 1.3-3824-g29c49ca54 - + NightVisionIllum @@ -316,7 +302,7 @@ Git: 1.3-3824-g29c49ca54 - + Viewport @@ -324,7 +310,7 @@ Git: 1.3-3824-g29c49ca54 - + SpeakerMuted @@ -335,7 +321,7 @@ Git: 1.3-3824-g29c49ca54 - + SpeakerVolumeLevel @@ -346,7 +332,7 @@ Git: 1.3-3824-g29c49ca54 - + SpeakerMaxLevel @@ -356,7 +342,7 @@ Git: 1.3-3824-g29c49ca54 - + SpeakerMinLevel @@ -366,7 +352,7 @@ Git: 1.3-3824-g29c49ca54 - + MicrophoneMuted @@ -374,7 +360,7 @@ Git: 1.3-3824-g29c49ca54 - + MicrophoneVolumeLevel @@ -382,21 +368,21 @@ Git: 1.3-3824-g29c49ca54 - + MicrophoneMaxLevel - + MicrophoneMinLevel - + MicrophoneAGCEnabled @@ -404,7 +390,7 @@ Git: 1.3-3824-g29c49ca54 - + ImageRotation @@ -412,7 +398,7 @@ Git: 1.3-3824-g29c49ca54 - + ImageFlipHorizontal @@ -420,7 +406,7 @@ Git: 1.3-3824-g29c49ca54 - + ImageFlipVertical @@ -428,7 +414,7 @@ Git: 1.3-3824-g29c49ca54 - + LocalVideoRecordingEnabled @@ -439,7 +425,7 @@ Git: 1.3-3824-g29c49ca54 - + LocalSnapshotRecordingEnabled @@ -450,13 +436,13 @@ Git: 1.3-3824-g29c49ca54 - + StatusLightEnabled - + StatusLightBrightness @@ -546,7 +532,7 @@ Git: 1.3-3824-g29c49ca54 This command SHALL allocate a snapshot stream on the device and return an allocated snapshot stream identifier. - + diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 39301cdc30..0912be1df2 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -677,7 +677,6 @@ "MinViewport", "MicrophoneCapabilities", "SpeakerCapabilities", - "CurrentSnapshotConfig", "Viewport" ] }, diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index c2de6acabf..3a62c4c84c 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -671,7 +671,6 @@ "MinViewport", "MicrophoneCapabilities", "SpeakerCapabilities", - "CurrentSnapshotConfig", "Viewport" ] }, diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 95f102ce08..31da395b05 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -9705,35 +9705,33 @@ provisional cluster CameraAvStreamManagement = 1361 { readonly attribute int32u maxNetworkBandwidth = 11; readonly attribute optional int16u currentFrameRate = 12; attribute access(read: manage, write: manage) optional boolean HDRModeEnabled = 13; - readonly attribute optional VideoCodecEnum currentVideoCodecs[] = 14; - readonly attribute optional SnapshotParamsStruct currentSnapshotConfig = 15; - readonly attribute fabric_idx fabricsUsingCamera[] = 16; - readonly attribute optional VideoStreamStruct allocatedVideoStreams[] = 17; - readonly attribute optional AudioStreamStruct allocatedAudioStreams[] = 18; - readonly attribute optional SnapshotStreamStruct allocatedSnapshotStreams[] = 19; - attribute access(read: administer, write: administer) optional StreamTypeEnum rankedVideoStreamPrioritiesList[] = 20; - attribute optional boolean softRecordingPrivacyModeEnabled = 21; - attribute optional boolean softLivestreamPrivacyModeEnabled = 22; - readonly attribute optional boolean hardPrivacyModeOn = 23; - attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVision = 24; - attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVisionIllum = 25; - attribute access(read: manage, write: manage) optional ViewportStruct viewport = 26; - attribute access(read: manage, write: manage) optional boolean speakerMuted = 27; - attribute access(read: manage, write: manage) optional int8u speakerVolumeLevel = 28; - readonly attribute access(read: manage) optional int8u speakerMaxLevel = 29; - readonly attribute access(read: manage) optional int8u speakerMinLevel = 30; - attribute access(read: manage, write: manage) optional boolean microphoneMuted = 31; - attribute access(read: manage, write: manage) optional int8u microphoneVolumeLevel = 32; - readonly attribute access(read: manage) optional int8u microphoneMaxLevel = 33; - readonly attribute access(read: manage) optional int8u microphoneMinLevel = 34; - attribute access(read: manage, write: manage) optional boolean microphoneAGCEnabled = 35; - attribute access(read: manage, write: manage) optional int16u imageRotation = 36; - attribute access(read: manage, write: manage) optional boolean imageFlipHorizontal = 37; - attribute access(read: manage, write: manage) optional boolean imageFlipVertical = 38; - attribute access(read: manage, write: manage) optional boolean localVideoRecordingEnabled = 39; - attribute access(read: manage, write: manage) optional boolean localSnapshotRecordingEnabled = 40; - attribute access(read: manage, write: manage) optional boolean statusLightEnabled = 41; - attribute access(read: manage, write: manage) optional ThreeLevelAutoEnum statusLightBrightness = 42; + readonly attribute fabric_idx fabricsUsingCamera[] = 14; + readonly attribute optional VideoStreamStruct allocatedVideoStreams[] = 15; + readonly attribute optional AudioStreamStruct allocatedAudioStreams[] = 16; + readonly attribute optional SnapshotStreamStruct allocatedSnapshotStreams[] = 17; + readonly attribute optional StreamTypeEnum rankedVideoStreamPrioritiesList[] = 18; + attribute optional boolean softRecordingPrivacyModeEnabled = 19; + attribute optional boolean softLivestreamPrivacyModeEnabled = 20; + readonly attribute optional boolean hardPrivacyModeOn = 21; + attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVision = 22; + attribute access(read: manage, write: manage) optional TriStateAutoEnum nightVisionIllum = 23; + attribute access(read: manage, write: manage) optional ViewportStruct viewport = 24; + attribute access(read: manage, write: manage) optional boolean speakerMuted = 25; + attribute access(read: manage, write: manage) optional int8u speakerVolumeLevel = 26; + readonly attribute access(read: manage) optional int8u speakerMaxLevel = 27; + readonly attribute access(read: manage) optional int8u speakerMinLevel = 28; + attribute access(read: manage, write: manage) optional boolean microphoneMuted = 29; + attribute access(read: manage, write: manage) optional int8u microphoneVolumeLevel = 30; + readonly attribute access(read: manage) optional int8u microphoneMaxLevel = 31; + readonly attribute access(read: manage) optional int8u microphoneMinLevel = 32; + attribute access(read: manage, write: manage) optional boolean microphoneAGCEnabled = 33; + attribute access(read: manage, write: manage) optional int16u imageRotation = 34; + attribute access(read: manage, write: manage) optional boolean imageFlipHorizontal = 35; + attribute access(read: manage, write: manage) optional boolean imageFlipVertical = 36; + attribute access(read: manage, write: manage) optional boolean localVideoRecordingEnabled = 37; + attribute access(read: manage, write: manage) optional boolean localSnapshotRecordingEnabled = 38; + attribute access(read: manage, write: manage) optional boolean statusLightEnabled = 39; + attribute access(read: manage, write: manage) optional ThreeLevelAutoEnum statusLightBrightness = 40; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -9790,7 +9788,7 @@ provisional cluster CameraAvStreamManagement = 1361 { request struct SnapshotStreamAllocateRequest { ImageCodecEnum imageCodec = 0; - int16u frameRate = 1; + int16u maxFrameRate = 1; int32u bitRate = 2; VideoResolutionStruct minResolution = 3; VideoResolutionStruct maxResolution = 4; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index a37be0ed91..228e0236ed 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -59738,35 +59738,33 @@ public static class CameraAvStreamManagementCluster extends BaseChipCluster { private static final long MAX_NETWORK_BANDWIDTH_ATTRIBUTE_ID = 11L; private static final long CURRENT_FRAME_RATE_ATTRIBUTE_ID = 12L; private static final long HDR_MODE_ENABLED_ATTRIBUTE_ID = 13L; - private static final long CURRENT_VIDEO_CODECS_ATTRIBUTE_ID = 14L; - private static final long CURRENT_SNAPSHOT_CONFIG_ATTRIBUTE_ID = 15L; - private static final long FABRICS_USING_CAMERA_ATTRIBUTE_ID = 16L; - private static final long ALLOCATED_VIDEO_STREAMS_ATTRIBUTE_ID = 17L; - private static final long ALLOCATED_AUDIO_STREAMS_ATTRIBUTE_ID = 18L; - private static final long ALLOCATED_SNAPSHOT_STREAMS_ATTRIBUTE_ID = 19L; - private static final long RANKED_VIDEO_STREAM_PRIORITIES_LIST_ATTRIBUTE_ID = 20L; - private static final long SOFT_RECORDING_PRIVACY_MODE_ENABLED_ATTRIBUTE_ID = 21L; - private static final long SOFT_LIVESTREAM_PRIVACY_MODE_ENABLED_ATTRIBUTE_ID = 22L; - private static final long HARD_PRIVACY_MODE_ON_ATTRIBUTE_ID = 23L; - private static final long NIGHT_VISION_ATTRIBUTE_ID = 24L; - private static final long NIGHT_VISION_ILLUM_ATTRIBUTE_ID = 25L; - private static final long VIEWPORT_ATTRIBUTE_ID = 26L; - private static final long SPEAKER_MUTED_ATTRIBUTE_ID = 27L; - private static final long SPEAKER_VOLUME_LEVEL_ATTRIBUTE_ID = 28L; - private static final long SPEAKER_MAX_LEVEL_ATTRIBUTE_ID = 29L; - private static final long SPEAKER_MIN_LEVEL_ATTRIBUTE_ID = 30L; - private static final long MICROPHONE_MUTED_ATTRIBUTE_ID = 31L; - private static final long MICROPHONE_VOLUME_LEVEL_ATTRIBUTE_ID = 32L; - private static final long MICROPHONE_MAX_LEVEL_ATTRIBUTE_ID = 33L; - private static final long MICROPHONE_MIN_LEVEL_ATTRIBUTE_ID = 34L; - private static final long MICROPHONE_AGC_ENABLED_ATTRIBUTE_ID = 35L; - private static final long IMAGE_ROTATION_ATTRIBUTE_ID = 36L; - private static final long IMAGE_FLIP_HORIZONTAL_ATTRIBUTE_ID = 37L; - private static final long IMAGE_FLIP_VERTICAL_ATTRIBUTE_ID = 38L; - private static final long LOCAL_VIDEO_RECORDING_ENABLED_ATTRIBUTE_ID = 39L; - private static final long LOCAL_SNAPSHOT_RECORDING_ENABLED_ATTRIBUTE_ID = 40L; - private static final long STATUS_LIGHT_ENABLED_ATTRIBUTE_ID = 41L; - private static final long STATUS_LIGHT_BRIGHTNESS_ATTRIBUTE_ID = 42L; + private static final long FABRICS_USING_CAMERA_ATTRIBUTE_ID = 14L; + private static final long ALLOCATED_VIDEO_STREAMS_ATTRIBUTE_ID = 15L; + private static final long ALLOCATED_AUDIO_STREAMS_ATTRIBUTE_ID = 16L; + private static final long ALLOCATED_SNAPSHOT_STREAMS_ATTRIBUTE_ID = 17L; + private static final long RANKED_VIDEO_STREAM_PRIORITIES_LIST_ATTRIBUTE_ID = 18L; + private static final long SOFT_RECORDING_PRIVACY_MODE_ENABLED_ATTRIBUTE_ID = 19L; + private static final long SOFT_LIVESTREAM_PRIVACY_MODE_ENABLED_ATTRIBUTE_ID = 20L; + private static final long HARD_PRIVACY_MODE_ON_ATTRIBUTE_ID = 21L; + private static final long NIGHT_VISION_ATTRIBUTE_ID = 22L; + private static final long NIGHT_VISION_ILLUM_ATTRIBUTE_ID = 23L; + private static final long VIEWPORT_ATTRIBUTE_ID = 24L; + private static final long SPEAKER_MUTED_ATTRIBUTE_ID = 25L; + private static final long SPEAKER_VOLUME_LEVEL_ATTRIBUTE_ID = 26L; + private static final long SPEAKER_MAX_LEVEL_ATTRIBUTE_ID = 27L; + private static final long SPEAKER_MIN_LEVEL_ATTRIBUTE_ID = 28L; + private static final long MICROPHONE_MUTED_ATTRIBUTE_ID = 29L; + private static final long MICROPHONE_VOLUME_LEVEL_ATTRIBUTE_ID = 30L; + private static final long MICROPHONE_MAX_LEVEL_ATTRIBUTE_ID = 31L; + private static final long MICROPHONE_MIN_LEVEL_ATTRIBUTE_ID = 32L; + private static final long MICROPHONE_AGC_ENABLED_ATTRIBUTE_ID = 33L; + private static final long IMAGE_ROTATION_ATTRIBUTE_ID = 34L; + private static final long IMAGE_FLIP_HORIZONTAL_ATTRIBUTE_ID = 35L; + private static final long IMAGE_FLIP_VERTICAL_ATTRIBUTE_ID = 36L; + private static final long LOCAL_VIDEO_RECORDING_ENABLED_ATTRIBUTE_ID = 37L; + private static final long LOCAL_SNAPSHOT_RECORDING_ENABLED_ATTRIBUTE_ID = 38L; + private static final long STATUS_LIGHT_ENABLED_ATTRIBUTE_ID = 39L; + private static final long STATUS_LIGHT_BRIGHTNESS_ATTRIBUTE_ID = 40L; private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L; private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L; private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L; @@ -59980,11 +59978,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, commandArgs, timedInvokeTimeoutMs); } - public void snapshotStreamAllocate(SnapshotStreamAllocateResponseCallback callback, Integer imageCodec, Integer frameRate, Long bitRate, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct minResolution, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct maxResolution, Integer quality) { - snapshotStreamAllocate(callback, imageCodec, frameRate, bitRate, minResolution, maxResolution, quality, 0); + public void snapshotStreamAllocate(SnapshotStreamAllocateResponseCallback callback, Integer imageCodec, Integer maxFrameRate, Long bitRate, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct minResolution, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct maxResolution, Integer quality) { + snapshotStreamAllocate(callback, imageCodec, maxFrameRate, bitRate, minResolution, maxResolution, quality, 0); } - public void snapshotStreamAllocate(SnapshotStreamAllocateResponseCallback callback, Integer imageCodec, Integer frameRate, Long bitRate, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct minResolution, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct maxResolution, Integer quality, int timedInvokeTimeoutMs) { + public void snapshotStreamAllocate(SnapshotStreamAllocateResponseCallback callback, Integer imageCodec, Integer maxFrameRate, Long bitRate, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct minResolution, ChipStructs.CameraAvStreamManagementClusterVideoResolutionStruct maxResolution, Integer quality, int timedInvokeTimeoutMs) { final long commandId = 7L; ArrayList elements = new ArrayList<>(); @@ -59992,9 +59990,9 @@ public void snapshotStreamAllocate(SnapshotStreamAllocateResponseCallback callba BaseTLVType imageCodectlvValue = new UIntType(imageCodec); elements.add(new StructElement(imageCodecFieldID, imageCodectlvValue)); - final long frameRateFieldID = 1L; - BaseTLVType frameRatetlvValue = new UIntType(frameRate); - elements.add(new StructElement(frameRateFieldID, frameRatetlvValue)); + final long maxFrameRateFieldID = 1L; + BaseTLVType maxFrameRatetlvValue = new UIntType(maxFrameRate); + elements.add(new StructElement(maxFrameRateFieldID, maxFrameRatetlvValue)); final long bitRateFieldID = 2L; BaseTLVType bitRatetlvValue = new UIntType(bitRate); @@ -60130,14 +60128,6 @@ public interface SupportedSnapshotParamsAttributeCallback extends BaseAttributeC void onSuccess(List value); } - public interface CurrentVideoCodecsAttributeCallback extends BaseAttributeCallback { - void onSuccess(List value); - } - - public interface CurrentSnapshotConfigAttributeCallback extends BaseAttributeCallback { - void onSuccess(ChipStructs.CameraAvStreamManagementClusterSnapshotParamsStruct value); - } - public interface FabricsUsingCameraAttributeCallback extends BaseAttributeCallback { void onSuccess(List value); } @@ -60551,58 +60541,6 @@ public void onSuccess(byte[] tlv) { }, HDR_MODE_ENABLED_ATTRIBUTE_ID, minInterval, maxInterval); } - public void readCurrentVideoCodecsAttribute( - CurrentVideoCodecsAttributeCallback callback) { - ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, CURRENT_VIDEO_CODECS_ATTRIBUTE_ID); - - readAttribute(new ReportCallbackImpl(callback, path) { - @Override - public void onSuccess(byte[] tlv) { - List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); - callback.onSuccess(value); - } - }, CURRENT_VIDEO_CODECS_ATTRIBUTE_ID, true); - } - - public void subscribeCurrentVideoCodecsAttribute( - CurrentVideoCodecsAttributeCallback callback, int minInterval, int maxInterval) { - ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, CURRENT_VIDEO_CODECS_ATTRIBUTE_ID); - - subscribeAttribute(new ReportCallbackImpl(callback, path) { - @Override - public void onSuccess(byte[] tlv) { - List value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); - callback.onSuccess(value); - } - }, CURRENT_VIDEO_CODECS_ATTRIBUTE_ID, minInterval, maxInterval); - } - - public void readCurrentSnapshotConfigAttribute( - CurrentSnapshotConfigAttributeCallback callback) { - ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, CURRENT_SNAPSHOT_CONFIG_ATTRIBUTE_ID); - - readAttribute(new ReportCallbackImpl(callback, path) { - @Override - public void onSuccess(byte[] tlv) { - ChipStructs.CameraAvStreamManagementClusterSnapshotParamsStruct value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); - callback.onSuccess(value); - } - }, CURRENT_SNAPSHOT_CONFIG_ATTRIBUTE_ID, true); - } - - public void subscribeCurrentSnapshotConfigAttribute( - CurrentSnapshotConfigAttributeCallback callback, int minInterval, int maxInterval) { - ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, CURRENT_SNAPSHOT_CONFIG_ATTRIBUTE_ID); - - subscribeAttribute(new ReportCallbackImpl(callback, path) { - @Override - public void onSuccess(byte[] tlv) { - ChipStructs.CameraAvStreamManagementClusterSnapshotParamsStruct value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); - callback.onSuccess(value); - } - }, CURRENT_SNAPSHOT_CONFIG_ATTRIBUTE_ID, minInterval, maxInterval); - } - public void readFabricsUsingCameraAttribute( FabricsUsingCameraAttributeCallback callback) { ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, FABRICS_USING_CAMERA_ATTRIBUTE_ID); @@ -60720,15 +60658,6 @@ public void onSuccess(byte[] tlv) { }, RANKED_VIDEO_STREAM_PRIORITIES_LIST_ATTRIBUTE_ID, true); } - public void writeRankedVideoStreamPrioritiesListAttribute(DefaultClusterCallback callback, ArrayList value) { - writeRankedVideoStreamPrioritiesListAttribute(callback, value, 0); - } - - public void writeRankedVideoStreamPrioritiesListAttribute(DefaultClusterCallback callback, ArrayList value, int timedWriteTimeoutMs) { - BaseTLVType tlvValue = ArrayType.generateArrayType(value, (elementvalue) -> new UIntType(elementvalue)); - writeAttribute(new WriteAttributesCallbackImpl(callback), RANKED_VIDEO_STREAM_PRIORITIES_LIST_ATTRIBUTE_ID, tlvValue, timedWriteTimeoutMs); - } - public void subscribeRankedVideoStreamPrioritiesListAttribute( RankedVideoStreamPrioritiesListAttributeCallback callback, int minInterval, int maxInterval) { ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, RANKED_VIDEO_STREAM_PRIORITIES_LIST_ATTRIBUTE_ID); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index 0f40fb5c32..86a43781fe 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -17087,35 +17087,33 @@ public enum Attribute { MaxNetworkBandwidth(11L), CurrentFrameRate(12L), HDRModeEnabled(13L), - CurrentVideoCodecs(14L), - CurrentSnapshotConfig(15L), - FabricsUsingCamera(16L), - AllocatedVideoStreams(17L), - AllocatedAudioStreams(18L), - AllocatedSnapshotStreams(19L), - RankedVideoStreamPrioritiesList(20L), - SoftRecordingPrivacyModeEnabled(21L), - SoftLivestreamPrivacyModeEnabled(22L), - HardPrivacyModeOn(23L), - NightVision(24L), - NightVisionIllum(25L), - Viewport(26L), - SpeakerMuted(27L), - SpeakerVolumeLevel(28L), - SpeakerMaxLevel(29L), - SpeakerMinLevel(30L), - MicrophoneMuted(31L), - MicrophoneVolumeLevel(32L), - MicrophoneMaxLevel(33L), - MicrophoneMinLevel(34L), - MicrophoneAGCEnabled(35L), - ImageRotation(36L), - ImageFlipHorizontal(37L), - ImageFlipVertical(38L), - LocalVideoRecordingEnabled(39L), - LocalSnapshotRecordingEnabled(40L), - StatusLightEnabled(41L), - StatusLightBrightness(42L), + FabricsUsingCamera(14L), + AllocatedVideoStreams(15L), + AllocatedAudioStreams(16L), + AllocatedSnapshotStreams(17L), + RankedVideoStreamPrioritiesList(18L), + SoftRecordingPrivacyModeEnabled(19L), + SoftLivestreamPrivacyModeEnabled(20L), + HardPrivacyModeOn(21L), + NightVision(22L), + NightVisionIllum(23L), + Viewport(24L), + SpeakerMuted(25L), + SpeakerVolumeLevel(26L), + SpeakerMaxLevel(27L), + SpeakerMinLevel(28L), + MicrophoneMuted(29L), + MicrophoneVolumeLevel(30L), + MicrophoneMaxLevel(31L), + MicrophoneMinLevel(32L), + MicrophoneAGCEnabled(33L), + ImageRotation(34L), + ImageFlipHorizontal(35L), + ImageFlipVertical(36L), + LocalVideoRecordingEnabled(37L), + LocalSnapshotRecordingEnabled(38L), + StatusLightEnabled(39L), + StatusLightBrightness(40L), GeneratedCommandList(65528L), AcceptedCommandList(65529L), EventList(65530L), @@ -17276,7 +17274,7 @@ public static VideoStreamDeallocateCommandField value(int id) throws NoSuchField } throw new NoSuchFieldError(); } - }public enum SnapshotStreamAllocateCommandField {ImageCodec(0),FrameRate(1),BitRate(2),MinResolution(3),MaxResolution(4),Quality(5),; + }public enum SnapshotStreamAllocateCommandField {ImageCodec(0),MaxFrameRate(1),BitRate(2),MinResolution(3),MaxResolution(4),Quality(5),; private final int id; SnapshotStreamAllocateCommandField(int id) { this.id = id; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index d60e57afa2..42e96815ef 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -20252,48 +20252,6 @@ public void onError(Exception ex) { } } - public static class DelegatedCameraAvStreamManagementClusterCurrentVideoCodecsAttributeCallback implements ChipClusters.CameraAvStreamManagementCluster.CurrentVideoCodecsAttributeCallback, DelegatedClusterCallback { - private ClusterCommandCallback callback; - @Override - public void setCallbackDelegate(ClusterCommandCallback callback) { - this.callback = callback; - } - - @Override - public void onSuccess(List valueList) { - Map responseValues = new LinkedHashMap<>(); - CommandResponseInfo commandResponseInfo = new CommandResponseInfo("valueList", "List"); - responseValues.put(commandResponseInfo, valueList); - callback.onSuccess(responseValues); - } - - @Override - public void onError(Exception ex) { - callback.onFailure(ex); - } - } - - public static class DelegatedCameraAvStreamManagementClusterCurrentSnapshotConfigAttributeCallback implements ChipClusters.CameraAvStreamManagementCluster.CurrentSnapshotConfigAttributeCallback, DelegatedClusterCallback { - private ClusterCommandCallback callback; - @Override - public void setCallbackDelegate(ClusterCommandCallback callback) { - this.callback = callback; - } - - @Override - public void onSuccess(ChipStructs.CameraAvStreamManagementClusterSnapshotParamsStruct value) { - Map responseValues = new LinkedHashMap<>(); - CommandResponseInfo commandResponseInfo = new CommandResponseInfo("value", "ChipStructs.CameraAvStreamManagementClusterSnapshotParamsStruct"); - responseValues.put(commandResponseInfo, value); - callback.onSuccess(responseValues); - } - - @Override - public void onError(Exception ex) { - callback.onFailure(ex); - } - } - public static class DelegatedCameraAvStreamManagementClusterFabricsUsingCameraAttributeCallback implements ChipClusters.CameraAvStreamManagementCluster.FabricsUsingCameraAttributeCallback, DelegatedClusterCallback { private ClusterCommandCallback callback; @Override @@ -29807,8 +29765,8 @@ public Map> getCommandMap() { CommandParameterInfo cameraAvStreamManagementsnapshotStreamAllocateimageCodecCommandParameterInfo = new CommandParameterInfo("imageCodec", Integer.class, Integer.class); cameraAvStreamManagementsnapshotStreamAllocateCommandParams.put("imageCodec",cameraAvStreamManagementsnapshotStreamAllocateimageCodecCommandParameterInfo); - CommandParameterInfo cameraAvStreamManagementsnapshotStreamAllocateframeRateCommandParameterInfo = new CommandParameterInfo("frameRate", Integer.class, Integer.class); - cameraAvStreamManagementsnapshotStreamAllocateCommandParams.put("frameRate",cameraAvStreamManagementsnapshotStreamAllocateframeRateCommandParameterInfo); + CommandParameterInfo cameraAvStreamManagementsnapshotStreamAllocatemaxFrameRateCommandParameterInfo = new CommandParameterInfo("maxFrameRate", Integer.class, Integer.class); + cameraAvStreamManagementsnapshotStreamAllocateCommandParams.put("maxFrameRate",cameraAvStreamManagementsnapshotStreamAllocatemaxFrameRateCommandParameterInfo); CommandParameterInfo cameraAvStreamManagementsnapshotStreamAllocatebitRateCommandParameterInfo = new CommandParameterInfo("bitRate", Long.class, Long.class); cameraAvStreamManagementsnapshotStreamAllocateCommandParams.put("bitRate",cameraAvStreamManagementsnapshotStreamAllocatebitRateCommandParameterInfo); @@ -29825,7 +29783,7 @@ public Map> getCommandMap() { commandArguments.get("imageCodec") , (Integer) - commandArguments.get("frameRate") + commandArguments.get("maxFrameRate") , (Long) commandArguments.get("bitRate") diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java index eb1dcbafc1..85d8c24676 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java @@ -18406,17 +18406,6 @@ private static Map readCameraAvStreamManagementInteract readCameraAvStreamManagementHDRModeEnabledCommandParams ); result.put("readHDRModeEnabledAttribute", readCameraAvStreamManagementHDRModeEnabledAttributeInteractionInfo); - Map readCameraAvStreamManagementCurrentVideoCodecsCommandParams = new LinkedHashMap(); - InteractionInfo readCameraAvStreamManagementCurrentVideoCodecsAttributeInteractionInfo = new InteractionInfo( - (cluster, callback, commandArguments) -> { - ((ChipClusters.CameraAvStreamManagementCluster) cluster).readCurrentVideoCodecsAttribute( - (ChipClusters.CameraAvStreamManagementCluster.CurrentVideoCodecsAttributeCallback) callback - ); - }, - () -> new ClusterInfoMapping.DelegatedCameraAvStreamManagementClusterCurrentVideoCodecsAttributeCallback(), - readCameraAvStreamManagementCurrentVideoCodecsCommandParams - ); - result.put("readCurrentVideoCodecsAttribute", readCameraAvStreamManagementCurrentVideoCodecsAttributeInteractionInfo); Map readCameraAvStreamManagementFabricsUsingCameraCommandParams = new LinkedHashMap(); InteractionInfo readCameraAvStreamManagementFabricsUsingCameraAttributeInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/CameraAvStreamManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/CameraAvStreamManagementCluster.kt index 9a8e562d2f..ffcad10cbf 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/CameraAvStreamManagementCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/CameraAvStreamManagementCluster.kt @@ -133,29 +133,6 @@ class CameraAvStreamManagementCluster( object SubscriptionEstablished : SupportedSnapshotParamsAttributeSubscriptionState() } - class CurrentVideoCodecsAttribute(val value: List?) - - sealed class CurrentVideoCodecsAttributeSubscriptionState { - data class Success(val value: List?) : CurrentVideoCodecsAttributeSubscriptionState() - - data class Error(val exception: Exception) : CurrentVideoCodecsAttributeSubscriptionState() - - object SubscriptionEstablished : CurrentVideoCodecsAttributeSubscriptionState() - } - - class CurrentSnapshotConfigAttribute( - val value: CameraAvStreamManagementClusterSnapshotParamsStruct? - ) - - sealed class CurrentSnapshotConfigAttributeSubscriptionState { - data class Success(val value: CameraAvStreamManagementClusterSnapshotParamsStruct?) : - CurrentSnapshotConfigAttributeSubscriptionState() - - data class Error(val exception: Exception) : CurrentSnapshotConfigAttributeSubscriptionState() - - object SubscriptionEstablished : CurrentSnapshotConfigAttributeSubscriptionState() - } - class FabricsUsingCameraAttribute(val value: List) sealed class FabricsUsingCameraAttributeSubscriptionState { @@ -511,7 +488,7 @@ class CameraAvStreamManagementCluster( suspend fun snapshotStreamAllocate( imageCodec: UByte, - frameRate: UShort, + maxFrameRate: UShort, bitRate: UInt, minResolution: CameraAvStreamManagementClusterVideoResolutionStruct, maxResolution: CameraAvStreamManagementClusterVideoResolutionStruct, @@ -526,8 +503,8 @@ class CameraAvStreamManagementCluster( val TAG_IMAGE_CODEC_REQ: Int = 0 tlvWriter.put(ContextSpecificTag(TAG_IMAGE_CODEC_REQ), imageCodec) - val TAG_FRAME_RATE_REQ: Int = 1 - tlvWriter.put(ContextSpecificTag(TAG_FRAME_RATE_REQ), frameRate) + val TAG_MAX_FRAME_RATE_REQ: Int = 1 + tlvWriter.put(ContextSpecificTag(TAG_MAX_FRAME_RATE_REQ), maxFrameRate) val TAG_BIT_RATE_REQ: Int = 2 tlvWriter.put(ContextSpecificTag(TAG_BIT_RATE_REQ), bitRate) @@ -2039,206 +2016,8 @@ class CameraAvStreamManagementCluster( } } - suspend fun readCurrentVideoCodecsAttribute(): CurrentVideoCodecsAttribute { - val ATTRIBUTE_ID: UInt = 14u - - val attributePath = - AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) - - val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) - - val response = controller.read(readRequest) - - if (response.successes.isEmpty()) { - logger.log(Level.WARNING, "Read command failed") - throw IllegalStateException("Read command failed with failures: ${response.failures}") - } - - logger.log(Level.FINE, "Read command succeeded") - - val attributeData = - response.successes.filterIsInstance().firstOrNull { - it.path.attributeId == ATTRIBUTE_ID - } - - requireNotNull(attributeData) { "Currentvideocodecs attribute not found in response" } - - // Decode the TLV data into the appropriate type - val tlvReader = TlvReader(attributeData.data) - val decodedValue: List? = - if (tlvReader.isNextTag(AnonymousTag)) { - buildList { - tlvReader.enterArray(AnonymousTag) - while (!tlvReader.isEndOfContainer()) { - add(tlvReader.getUByte(AnonymousTag)) - } - tlvReader.exitContainer() - } - } else { - null - } - - return CurrentVideoCodecsAttribute(decodedValue) - } - - suspend fun subscribeCurrentVideoCodecsAttribute( - minInterval: Int, - maxInterval: Int, - ): Flow { - val ATTRIBUTE_ID: UInt = 14u - val attributePaths = - listOf( - AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) - ) - - val subscribeRequest: SubscribeRequest = - SubscribeRequest( - eventPaths = emptyList(), - attributePaths = attributePaths, - minInterval = Duration.ofSeconds(minInterval.toLong()), - maxInterval = Duration.ofSeconds(maxInterval.toLong()), - ) - - return controller.subscribe(subscribeRequest).transform { subscriptionState -> - when (subscriptionState) { - is SubscriptionState.SubscriptionErrorNotification -> { - emit( - CurrentVideoCodecsAttributeSubscriptionState.Error( - Exception( - "Subscription terminated with error code: ${subscriptionState.terminationCause}" - ) - ) - ) - } - is SubscriptionState.NodeStateUpdate -> { - val attributeData = - subscriptionState.updateState.successes - .filterIsInstance() - .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } - - requireNotNull(attributeData) { - "Currentvideocodecs attribute not found in Node State update" - } - - // Decode the TLV data into the appropriate type - val tlvReader = TlvReader(attributeData.data) - val decodedValue: List? = - if (tlvReader.isNextTag(AnonymousTag)) { - buildList { - tlvReader.enterArray(AnonymousTag) - while (!tlvReader.isEndOfContainer()) { - add(tlvReader.getUByte(AnonymousTag)) - } - tlvReader.exitContainer() - } - } else { - null - } - - decodedValue?.let { emit(CurrentVideoCodecsAttributeSubscriptionState.Success(it)) } - } - SubscriptionState.SubscriptionEstablished -> { - emit(CurrentVideoCodecsAttributeSubscriptionState.SubscriptionEstablished) - } - } - } - } - - suspend fun readCurrentSnapshotConfigAttribute(): CurrentSnapshotConfigAttribute { - val ATTRIBUTE_ID: UInt = 15u - - val attributePath = - AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) - - val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) - - val response = controller.read(readRequest) - - if (response.successes.isEmpty()) { - logger.log(Level.WARNING, "Read command failed") - throw IllegalStateException("Read command failed with failures: ${response.failures}") - } - - logger.log(Level.FINE, "Read command succeeded") - - val attributeData = - response.successes.filterIsInstance().firstOrNull { - it.path.attributeId == ATTRIBUTE_ID - } - - requireNotNull(attributeData) { "Currentsnapshotconfig attribute not found in response" } - - // Decode the TLV data into the appropriate type - val tlvReader = TlvReader(attributeData.data) - val decodedValue: CameraAvStreamManagementClusterSnapshotParamsStruct? = - if (tlvReader.isNextTag(AnonymousTag)) { - CameraAvStreamManagementClusterSnapshotParamsStruct.fromTlv(AnonymousTag, tlvReader) - } else { - null - } - - return CurrentSnapshotConfigAttribute(decodedValue) - } - - suspend fun subscribeCurrentSnapshotConfigAttribute( - minInterval: Int, - maxInterval: Int, - ): Flow { - val ATTRIBUTE_ID: UInt = 15u - val attributePaths = - listOf( - AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) - ) - - val subscribeRequest: SubscribeRequest = - SubscribeRequest( - eventPaths = emptyList(), - attributePaths = attributePaths, - minInterval = Duration.ofSeconds(minInterval.toLong()), - maxInterval = Duration.ofSeconds(maxInterval.toLong()), - ) - - return controller.subscribe(subscribeRequest).transform { subscriptionState -> - when (subscriptionState) { - is SubscriptionState.SubscriptionErrorNotification -> { - emit( - CurrentSnapshotConfigAttributeSubscriptionState.Error( - Exception( - "Subscription terminated with error code: ${subscriptionState.terminationCause}" - ) - ) - ) - } - is SubscriptionState.NodeStateUpdate -> { - val attributeData = - subscriptionState.updateState.successes - .filterIsInstance() - .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } - - requireNotNull(attributeData) { - "Currentsnapshotconfig attribute not found in Node State update" - } - - // Decode the TLV data into the appropriate type - val tlvReader = TlvReader(attributeData.data) - val decodedValue: CameraAvStreamManagementClusterSnapshotParamsStruct? = - if (tlvReader.isNextTag(AnonymousTag)) { - CameraAvStreamManagementClusterSnapshotParamsStruct.fromTlv(AnonymousTag, tlvReader) - } else { - null - } - - decodedValue?.let { emit(CurrentSnapshotConfigAttributeSubscriptionState.Success(it)) } - } - SubscriptionState.SubscriptionEstablished -> { - emit(CurrentSnapshotConfigAttributeSubscriptionState.SubscriptionEstablished) - } - } - } - } - suspend fun readFabricsUsingCameraAttribute(): FabricsUsingCameraAttribute { - val ATTRIBUTE_ID: UInt = 16u + val ATTRIBUTE_ID: UInt = 14u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2279,7 +2058,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 16u + val ATTRIBUTE_ID: UInt = 14u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2335,7 +2114,7 @@ class CameraAvStreamManagementCluster( } suspend fun readAllocatedVideoStreamsAttribute(): AllocatedVideoStreamsAttribute { - val ATTRIBUTE_ID: UInt = 17u + val ATTRIBUTE_ID: UInt = 15u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2380,7 +2159,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 17u + val ATTRIBUTE_ID: UInt = 15u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2445,7 +2224,7 @@ class CameraAvStreamManagementCluster( } suspend fun readAllocatedAudioStreamsAttribute(): AllocatedAudioStreamsAttribute { - val ATTRIBUTE_ID: UInt = 18u + val ATTRIBUTE_ID: UInt = 16u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2490,7 +2269,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 18u + val ATTRIBUTE_ID: UInt = 16u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2555,7 +2334,7 @@ class CameraAvStreamManagementCluster( } suspend fun readAllocatedSnapshotStreamsAttribute(): AllocatedSnapshotStreamsAttribute { - val ATTRIBUTE_ID: UInt = 19u + val ATTRIBUTE_ID: UInt = 17u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2602,7 +2381,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 19u + val ATTRIBUTE_ID: UInt = 17u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2668,7 +2447,7 @@ class CameraAvStreamManagementCluster( suspend fun readRankedVideoStreamPrioritiesListAttribute(): RankedVideoStreamPrioritiesListAttribute { - val ATTRIBUTE_ID: UInt = 20u + val ATTRIBUTE_ID: UInt = 18u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2711,58 +2490,11 @@ class CameraAvStreamManagementCluster( return RankedVideoStreamPrioritiesListAttribute(decodedValue) } - suspend fun writeRankedVideoStreamPrioritiesListAttribute( - value: List, - timedWriteTimeout: Duration? = null, - ) { - val ATTRIBUTE_ID: UInt = 20u - - val tlvWriter = TlvWriter() - tlvWriter.startArray(AnonymousTag) - for (item in value.iterator()) { - tlvWriter.put(AnonymousTag, item) - } - tlvWriter.endArray() - - val writeRequests: WriteRequests = - WriteRequests( - requests = - listOf( - WriteRequest( - attributePath = - AttributePath(endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID), - tlvPayload = tlvWriter.getEncoded(), - ) - ), - timedRequest = timedWriteTimeout, - ) - - val response: WriteResponse = controller.write(writeRequests) - - when (response) { - is WriteResponse.Success -> { - logger.log(Level.FINE, "Write command succeeded") - } - is WriteResponse.PartialWriteFailure -> { - val aggregatedErrorMessage = - response.failures.joinToString("\n") { failure -> - "Error at ${failure.attributePath}: ${failure.ex.message}" - } - - response.failures.forEach { failure -> - logger.log(Level.WARNING, "Error at ${failure.attributePath}: ${failure.ex.message}") - } - - throw IllegalStateException("Write command failed with errors: \n$aggregatedErrorMessage") - } - } - } - suspend fun subscribeRankedVideoStreamPrioritiesListAttribute( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 20u + val ATTRIBUTE_ID: UInt = 18u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2824,7 +2556,7 @@ class CameraAvStreamManagementCluster( } suspend fun readSoftRecordingPrivacyModeEnabledAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 21u + val ATTRIBUTE_ID: UInt = 19u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2865,7 +2597,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 21u + val ATTRIBUTE_ID: UInt = 19u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -2908,7 +2640,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 21u + val ATTRIBUTE_ID: UInt = 19u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -2962,7 +2694,7 @@ class CameraAvStreamManagementCluster( } suspend fun readSoftLivestreamPrivacyModeEnabledAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 22u + val ATTRIBUTE_ID: UInt = 20u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3003,7 +2735,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 22u + val ATTRIBUTE_ID: UInt = 20u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -3046,7 +2778,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 22u + val ATTRIBUTE_ID: UInt = 20u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3100,7 +2832,7 @@ class CameraAvStreamManagementCluster( } suspend fun readHardPrivacyModeOnAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 23u + val ATTRIBUTE_ID: UInt = 21u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3139,7 +2871,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 23u + val ATTRIBUTE_ID: UInt = 21u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3193,7 +2925,7 @@ class CameraAvStreamManagementCluster( } suspend fun readNightVisionAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 24u + val ATTRIBUTE_ID: UInt = 22u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3229,7 +2961,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeNightVisionAttribute(value: UByte, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 24u + val ATTRIBUTE_ID: UInt = 22u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -3272,7 +3004,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 24u + val ATTRIBUTE_ID: UInt = 22u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3324,7 +3056,7 @@ class CameraAvStreamManagementCluster( } suspend fun readNightVisionIllumAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 25u + val ATTRIBUTE_ID: UInt = 23u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3360,7 +3092,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeNightVisionIllumAttribute(value: UByte, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 25u + val ATTRIBUTE_ID: UInt = 23u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -3403,7 +3135,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 25u + val ATTRIBUTE_ID: UInt = 23u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3457,7 +3189,7 @@ class CameraAvStreamManagementCluster( } suspend fun readViewportAttribute(): ViewportAttribute { - val ATTRIBUTE_ID: UInt = 26u + val ATTRIBUTE_ID: UInt = 24u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3496,7 +3228,7 @@ class CameraAvStreamManagementCluster( value: CameraAvStreamManagementClusterViewportStruct, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 26u + val ATTRIBUTE_ID: UInt = 24u val tlvWriter = TlvWriter() value.toTlv(AnonymousTag, tlvWriter) @@ -3539,7 +3271,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 26u + val ATTRIBUTE_ID: UInt = 24u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3591,7 +3323,7 @@ class CameraAvStreamManagementCluster( } suspend fun readSpeakerMutedAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 27u + val ATTRIBUTE_ID: UInt = 25u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3627,7 +3359,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeSpeakerMutedAttribute(value: Boolean, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 27u + val ATTRIBUTE_ID: UInt = 25u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -3670,7 +3402,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 27u + val ATTRIBUTE_ID: UInt = 25u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3722,7 +3454,7 @@ class CameraAvStreamManagementCluster( } suspend fun readSpeakerVolumeLevelAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 28u + val ATTRIBUTE_ID: UInt = 26u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3758,7 +3490,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeSpeakerVolumeLevelAttribute(value: UByte, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 28u + val ATTRIBUTE_ID: UInt = 26u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -3801,7 +3533,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 28u + val ATTRIBUTE_ID: UInt = 26u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3855,7 +3587,7 @@ class CameraAvStreamManagementCluster( } suspend fun readSpeakerMaxLevelAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 29u + val ATTRIBUTE_ID: UInt = 27u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3894,7 +3626,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 29u + val ATTRIBUTE_ID: UInt = 27u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3948,7 +3680,7 @@ class CameraAvStreamManagementCluster( } suspend fun readSpeakerMinLevelAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 30u + val ATTRIBUTE_ID: UInt = 28u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -3987,7 +3719,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 30u + val ATTRIBUTE_ID: UInt = 28u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4041,7 +3773,7 @@ class CameraAvStreamManagementCluster( } suspend fun readMicrophoneMutedAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 31u + val ATTRIBUTE_ID: UInt = 29u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4077,7 +3809,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeMicrophoneMutedAttribute(value: Boolean, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 31u + val ATTRIBUTE_ID: UInt = 29u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -4120,7 +3852,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 31u + val ATTRIBUTE_ID: UInt = 29u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4174,7 +3906,7 @@ class CameraAvStreamManagementCluster( } suspend fun readMicrophoneVolumeLevelAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 32u + val ATTRIBUTE_ID: UInt = 30u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4213,7 +3945,7 @@ class CameraAvStreamManagementCluster( value: UByte, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 32u + val ATTRIBUTE_ID: UInt = 30u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -4256,7 +3988,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 32u + val ATTRIBUTE_ID: UInt = 30u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4310,7 +4042,7 @@ class CameraAvStreamManagementCluster( } suspend fun readMicrophoneMaxLevelAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 33u + val ATTRIBUTE_ID: UInt = 31u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4349,7 +4081,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 33u + val ATTRIBUTE_ID: UInt = 31u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4403,7 +4135,7 @@ class CameraAvStreamManagementCluster( } suspend fun readMicrophoneMinLevelAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 34u + val ATTRIBUTE_ID: UInt = 32u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4442,7 +4174,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 34u + val ATTRIBUTE_ID: UInt = 32u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4496,7 +4228,7 @@ class CameraAvStreamManagementCluster( } suspend fun readMicrophoneAGCEnabledAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 35u + val ATTRIBUTE_ID: UInt = 33u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4535,7 +4267,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 35u + val ATTRIBUTE_ID: UInt = 33u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -4578,7 +4310,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 35u + val ATTRIBUTE_ID: UInt = 33u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4632,7 +4364,7 @@ class CameraAvStreamManagementCluster( } suspend fun readImageRotationAttribute(): UShort? { - val ATTRIBUTE_ID: UInt = 36u + val ATTRIBUTE_ID: UInt = 34u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4668,7 +4400,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeImageRotationAttribute(value: UShort, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 36u + val ATTRIBUTE_ID: UInt = 34u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -4711,7 +4443,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 36u + val ATTRIBUTE_ID: UInt = 34u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4763,7 +4495,7 @@ class CameraAvStreamManagementCluster( } suspend fun readImageFlipHorizontalAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 37u + val ATTRIBUTE_ID: UInt = 35u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4802,7 +4534,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 37u + val ATTRIBUTE_ID: UInt = 35u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -4845,7 +4577,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 37u + val ATTRIBUTE_ID: UInt = 35u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4899,7 +4631,7 @@ class CameraAvStreamManagementCluster( } suspend fun readImageFlipVerticalAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 38u + val ATTRIBUTE_ID: UInt = 36u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -4935,7 +4667,7 @@ class CameraAvStreamManagementCluster( } suspend fun writeImageFlipVerticalAttribute(value: Boolean, timedWriteTimeout: Duration? = null) { - val ATTRIBUTE_ID: UInt = 38u + val ATTRIBUTE_ID: UInt = 36u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -4978,7 +4710,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 38u + val ATTRIBUTE_ID: UInt = 36u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5032,7 +4764,7 @@ class CameraAvStreamManagementCluster( } suspend fun readLocalVideoRecordingEnabledAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 39u + val ATTRIBUTE_ID: UInt = 37u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5071,7 +4803,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 39u + val ATTRIBUTE_ID: UInt = 37u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -5114,7 +4846,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 39u + val ATTRIBUTE_ID: UInt = 37u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5168,7 +4900,7 @@ class CameraAvStreamManagementCluster( } suspend fun readLocalSnapshotRecordingEnabledAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 40u + val ATTRIBUTE_ID: UInt = 38u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5209,7 +4941,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 40u + val ATTRIBUTE_ID: UInt = 38u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -5252,7 +4984,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 40u + val ATTRIBUTE_ID: UInt = 38u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5306,7 +5038,7 @@ class CameraAvStreamManagementCluster( } suspend fun readStatusLightEnabledAttribute(): Boolean? { - val ATTRIBUTE_ID: UInt = 41u + val ATTRIBUTE_ID: UInt = 39u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5345,7 +5077,7 @@ class CameraAvStreamManagementCluster( value: Boolean, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 41u + val ATTRIBUTE_ID: UInt = 39u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -5388,7 +5120,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 41u + val ATTRIBUTE_ID: UInt = 39u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5442,7 +5174,7 @@ class CameraAvStreamManagementCluster( } suspend fun readStatusLightBrightnessAttribute(): UByte? { - val ATTRIBUTE_ID: UInt = 42u + val ATTRIBUTE_ID: UInt = 40u val attributePath = AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) @@ -5481,7 +5213,7 @@ class CameraAvStreamManagementCluster( value: UByte, timedWriteTimeout: Duration? = null, ) { - val ATTRIBUTE_ID: UInt = 42u + val ATTRIBUTE_ID: UInt = 40u val tlvWriter = TlvWriter() tlvWriter.put(AnonymousTag, value) @@ -5524,7 +5256,7 @@ class CameraAvStreamManagementCluster( minInterval: Int, maxInterval: Int, ): Flow { - val ATTRIBUTE_ID: UInt = 42u + val ATTRIBUTE_ID: UInt = 40u val attributePaths = listOf( AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index d307822772..deddd974e4 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -40493,123 +40493,6 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR jnivalue, value); return value; } - case Attributes::CurrentVideoCodecs::Id: { - using TypeInfo = Attributes::CurrentVideoCodecs::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = app::DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) - { - return nullptr; - } - jobject value; - chip::JniReferences::GetInstance().CreateArrayList(value); - - auto iter_value_0 = cppValue.begin(); - while (iter_value_0.Next()) - { - auto & entry_0 = iter_value_0.GetValue(); - jobject newElement_0; - std::string newElement_0ClassName = "java/lang/Integer"; - std::string newElement_0CtorSignature = "(I)V"; - jint jninewElement_0 = static_cast(entry_0); - chip::JniReferences::GetInstance().CreateBoxedObject( - newElement_0ClassName.c_str(), newElement_0CtorSignature.c_str(), jninewElement_0, newElement_0); - chip::JniReferences::GetInstance().AddToList(value, newElement_0); - } - return value; - } - case Attributes::CurrentSnapshotConfig::Id: { - using TypeInfo = Attributes::CurrentSnapshotConfig::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = app::DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) - { - return nullptr; - } - jobject value; - jobject value_resolution; - jobject value_resolution_width; - std::string value_resolution_widthClassName = "java/lang/Integer"; - std::string value_resolution_widthCtorSignature = "(I)V"; - jint jnivalue_resolution_width = static_cast(cppValue.resolution.width); - chip::JniReferences::GetInstance().CreateBoxedObject(value_resolution_widthClassName.c_str(), - value_resolution_widthCtorSignature.c_str(), - jnivalue_resolution_width, value_resolution_width); - jobject value_resolution_height; - std::string value_resolution_heightClassName = "java/lang/Integer"; - std::string value_resolution_heightCtorSignature = "(I)V"; - jint jnivalue_resolution_height = static_cast(cppValue.resolution.height); - chip::JniReferences::GetInstance().CreateBoxedObject(value_resolution_heightClassName.c_str(), - value_resolution_heightCtorSignature.c_str(), - jnivalue_resolution_height, value_resolution_height); - - { - jclass videoResolutionStructStructClass_1; - err = chip::JniReferences::GetInstance().GetLocalClassRef( - env, "chip/devicecontroller/ChipStructs$CameraAvStreamManagementClusterVideoResolutionStruct", - videoResolutionStructStructClass_1); - if (err != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "Could not find class ChipStructs$CameraAvStreamManagementClusterVideoResolutionStruct"); - return nullptr; - } - - jmethodID videoResolutionStructStructCtor_1; - err = chip::JniReferences::GetInstance().FindMethod(env, videoResolutionStructStructClass_1, "", - "(Ljava/lang/Integer;Ljava/lang/Integer;)V", - &videoResolutionStructStructCtor_1); - if (err != CHIP_NO_ERROR || videoResolutionStructStructCtor_1 == nullptr) - { - ChipLogError(Zcl, - "Could not find ChipStructs$CameraAvStreamManagementClusterVideoResolutionStruct constructor"); - return nullptr; - } - - value_resolution = env->NewObject(videoResolutionStructStructClass_1, videoResolutionStructStructCtor_1, - value_resolution_width, value_resolution_height); - } - jobject value_maxFrameRate; - std::string value_maxFrameRateClassName = "java/lang/Integer"; - std::string value_maxFrameRateCtorSignature = "(I)V"; - jint jnivalue_maxFrameRate = static_cast(cppValue.maxFrameRate); - chip::JniReferences::GetInstance().CreateBoxedObject(value_maxFrameRateClassName.c_str(), - value_maxFrameRateCtorSignature.c_str(), - jnivalue_maxFrameRate, value_maxFrameRate); - jobject value_imageCodec; - std::string value_imageCodecClassName = "java/lang/Integer"; - std::string value_imageCodecCtorSignature = "(I)V"; - jint jnivalue_imageCodec = static_cast(cppValue.imageCodec); - chip::JniReferences::GetInstance().CreateBoxedObject( - value_imageCodecClassName.c_str(), value_imageCodecCtorSignature.c_str(), jnivalue_imageCodec, value_imageCodec); - - { - jclass snapshotParamsStructStructClass_0; - err = chip::JniReferences::GetInstance().GetLocalClassRef( - env, "chip/devicecontroller/ChipStructs$CameraAvStreamManagementClusterSnapshotParamsStruct", - snapshotParamsStructStructClass_0); - if (err != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "Could not find class ChipStructs$CameraAvStreamManagementClusterSnapshotParamsStruct"); - return nullptr; - } - - jmethodID snapshotParamsStructStructCtor_0; - err = chip::JniReferences::GetInstance().FindMethod( - env, snapshotParamsStructStructClass_0, "", - "(Lchip/devicecontroller/ChipStructs$CameraAvStreamManagementClusterVideoResolutionStruct;Ljava/lang/" - "Integer;Ljava/lang/Integer;)V", - &snapshotParamsStructStructCtor_0); - if (err != CHIP_NO_ERROR || snapshotParamsStructStructCtor_0 == nullptr) - { - ChipLogError(Zcl, "Could not find ChipStructs$CameraAvStreamManagementClusterSnapshotParamsStruct constructor"); - return nullptr; - } - - value = env->NewObject(snapshotParamsStructStructClass_0, snapshotParamsStructStructCtor_0, value_resolution, - value_maxFrameRate, value_imageCodec); - } - return value; - } case Attributes::FabricsUsingCamera::Id: { using TypeInfo = Attributes::FabricsUsingCamera::TypeInfo; TypeInfo::DecodableType cppValue; diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index ac906271d3..971bb232a0 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -12447,7 +12447,7 @@ class ChipClusters: "commandName": "SnapshotStreamAllocate", "args": { "imageCodec": "int", - "frameRate": "int", + "maxFrameRate": "int", "bitRate": "int", "minResolution": "VideoResolutionStruct", "maxResolution": "VideoResolutionStruct", @@ -12564,193 +12564,180 @@ class ChipClusters: "writable": True, }, 0x0000000E: { - "attributeName": "CurrentVideoCodecs", + "attributeName": "FabricsUsingCamera", "attributeId": 0x0000000E, "type": "int", "reportable": True, }, 0x0000000F: { - "attributeName": "CurrentSnapshotConfig", + "attributeName": "AllocatedVideoStreams", "attributeId": 0x0000000F, "type": "", "reportable": True, }, 0x00000010: { - "attributeName": "FabricsUsingCamera", + "attributeName": "AllocatedAudioStreams", "attributeId": 0x00000010, - "type": "int", + "type": "", "reportable": True, }, 0x00000011: { - "attributeName": "AllocatedVideoStreams", + "attributeName": "AllocatedSnapshotStreams", "attributeId": 0x00000011, "type": "", "reportable": True, }, 0x00000012: { - "attributeName": "AllocatedAudioStreams", + "attributeName": "RankedVideoStreamPrioritiesList", "attributeId": 0x00000012, - "type": "", + "type": "int", "reportable": True, }, 0x00000013: { - "attributeName": "AllocatedSnapshotStreams", + "attributeName": "SoftRecordingPrivacyModeEnabled", "attributeId": 0x00000013, - "type": "", + "type": "bool", "reportable": True, + "writable": True, }, 0x00000014: { - "attributeName": "RankedVideoStreamPrioritiesList", + "attributeName": "SoftLivestreamPrivacyModeEnabled", "attributeId": 0x00000014, - "type": "int", + "type": "bool", "reportable": True, "writable": True, }, 0x00000015: { - "attributeName": "SoftRecordingPrivacyModeEnabled", + "attributeName": "HardPrivacyModeOn", "attributeId": 0x00000015, "type": "bool", "reportable": True, - "writable": True, }, 0x00000016: { - "attributeName": "SoftLivestreamPrivacyModeEnabled", + "attributeName": "NightVision", "attributeId": 0x00000016, - "type": "bool", + "type": "int", "reportable": True, "writable": True, }, 0x00000017: { - "attributeName": "HardPrivacyModeOn", + "attributeName": "NightVisionIllum", "attributeId": 0x00000017, - "type": "bool", + "type": "int", "reportable": True, + "writable": True, }, 0x00000018: { - "attributeName": "NightVision", + "attributeName": "Viewport", "attributeId": 0x00000018, - "type": "int", + "type": "", "reportable": True, "writable": True, }, 0x00000019: { - "attributeName": "NightVisionIllum", + "attributeName": "SpeakerMuted", "attributeId": 0x00000019, - "type": "int", + "type": "bool", "reportable": True, "writable": True, }, 0x0000001A: { - "attributeName": "Viewport", + "attributeName": "SpeakerVolumeLevel", "attributeId": 0x0000001A, - "type": "", + "type": "int", "reportable": True, "writable": True, }, 0x0000001B: { - "attributeName": "SpeakerMuted", + "attributeName": "SpeakerMaxLevel", "attributeId": 0x0000001B, - "type": "bool", + "type": "int", "reportable": True, - "writable": True, }, 0x0000001C: { - "attributeName": "SpeakerVolumeLevel", + "attributeName": "SpeakerMinLevel", "attributeId": 0x0000001C, "type": "int", "reportable": True, - "writable": True, }, 0x0000001D: { - "attributeName": "SpeakerMaxLevel", + "attributeName": "MicrophoneMuted", "attributeId": 0x0000001D, - "type": "int", + "type": "bool", "reportable": True, + "writable": True, }, 0x0000001E: { - "attributeName": "SpeakerMinLevel", + "attributeName": "MicrophoneVolumeLevel", "attributeId": 0x0000001E, "type": "int", "reportable": True, + "writable": True, }, 0x0000001F: { - "attributeName": "MicrophoneMuted", + "attributeName": "MicrophoneMaxLevel", "attributeId": 0x0000001F, - "type": "bool", + "type": "int", "reportable": True, - "writable": True, }, 0x00000020: { - "attributeName": "MicrophoneVolumeLevel", + "attributeName": "MicrophoneMinLevel", "attributeId": 0x00000020, "type": "int", "reportable": True, - "writable": True, }, 0x00000021: { - "attributeName": "MicrophoneMaxLevel", + "attributeName": "MicrophoneAGCEnabled", "attributeId": 0x00000021, - "type": "int", + "type": "bool", "reportable": True, + "writable": True, }, 0x00000022: { - "attributeName": "MicrophoneMinLevel", + "attributeName": "ImageRotation", "attributeId": 0x00000022, "type": "int", "reportable": True, + "writable": True, }, 0x00000023: { - "attributeName": "MicrophoneAGCEnabled", + "attributeName": "ImageFlipHorizontal", "attributeId": 0x00000023, "type": "bool", "reportable": True, "writable": True, }, 0x00000024: { - "attributeName": "ImageRotation", + "attributeName": "ImageFlipVertical", "attributeId": 0x00000024, - "type": "int", + "type": "bool", "reportable": True, "writable": True, }, 0x00000025: { - "attributeName": "ImageFlipHorizontal", + "attributeName": "LocalVideoRecordingEnabled", "attributeId": 0x00000025, "type": "bool", "reportable": True, "writable": True, }, 0x00000026: { - "attributeName": "ImageFlipVertical", + "attributeName": "LocalSnapshotRecordingEnabled", "attributeId": 0x00000026, "type": "bool", "reportable": True, "writable": True, }, 0x00000027: { - "attributeName": "LocalVideoRecordingEnabled", + "attributeName": "StatusLightEnabled", "attributeId": 0x00000027, "type": "bool", "reportable": True, "writable": True, }, 0x00000028: { - "attributeName": "LocalSnapshotRecordingEnabled", - "attributeId": 0x00000028, - "type": "bool", - "reportable": True, - "writable": True, - }, - 0x00000029: { - "attributeName": "StatusLightEnabled", - "attributeId": 0x00000029, - "type": "bool", - "reportable": True, - "writable": True, - }, - 0x0000002A: { "attributeName": "StatusLightBrightness", - "attributeId": 0x0000002A, + "attributeId": 0x00000028, "type": "int", "reportable": True, "writable": True, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index c9a162ac0b..b27196c751 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -44790,35 +44790,33 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="maxNetworkBandwidth", Tag=0x0000000B, Type=uint), ClusterObjectFieldDescriptor(Label="currentFrameRate", Tag=0x0000000C, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="HDRModeEnabled", Tag=0x0000000D, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="currentVideoCodecs", Tag=0x0000000E, Type=typing.Optional[typing.List[CameraAvStreamManagement.Enums.VideoCodecEnum]]), - ClusterObjectFieldDescriptor(Label="currentSnapshotConfig", Tag=0x0000000F, Type=typing.Optional[CameraAvStreamManagement.Structs.SnapshotParamsStruct]), - ClusterObjectFieldDescriptor(Label="fabricsUsingCamera", Tag=0x00000010, Type=typing.List[uint]), - ClusterObjectFieldDescriptor(Label="allocatedVideoStreams", Tag=0x00000011, Type=typing.Optional[typing.List[CameraAvStreamManagement.Structs.VideoStreamStruct]]), - ClusterObjectFieldDescriptor(Label="allocatedAudioStreams", Tag=0x00000012, Type=typing.Optional[typing.List[CameraAvStreamManagement.Structs.AudioStreamStruct]]), - ClusterObjectFieldDescriptor(Label="allocatedSnapshotStreams", Tag=0x00000013, Type=typing.Optional[typing.List[CameraAvStreamManagement.Structs.SnapshotStreamStruct]]), - ClusterObjectFieldDescriptor(Label="rankedVideoStreamPrioritiesList", Tag=0x00000014, Type=typing.Optional[typing.List[CameraAvStreamManagement.Enums.StreamTypeEnum]]), - ClusterObjectFieldDescriptor(Label="softRecordingPrivacyModeEnabled", Tag=0x00000015, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="softLivestreamPrivacyModeEnabled", Tag=0x00000016, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="hardPrivacyModeOn", Tag=0x00000017, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="nightVision", Tag=0x00000018, Type=typing.Optional[CameraAvStreamManagement.Enums.TriStateAutoEnum]), - ClusterObjectFieldDescriptor(Label="nightVisionIllum", Tag=0x00000019, Type=typing.Optional[CameraAvStreamManagement.Enums.TriStateAutoEnum]), - ClusterObjectFieldDescriptor(Label="viewport", Tag=0x0000001A, Type=typing.Optional[CameraAvStreamManagement.Structs.ViewportStruct]), - ClusterObjectFieldDescriptor(Label="speakerMuted", Tag=0x0000001B, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="speakerVolumeLevel", Tag=0x0000001C, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="speakerMaxLevel", Tag=0x0000001D, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="speakerMinLevel", Tag=0x0000001E, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="microphoneMuted", Tag=0x0000001F, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="microphoneVolumeLevel", Tag=0x00000020, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="microphoneMaxLevel", Tag=0x00000021, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="microphoneMinLevel", Tag=0x00000022, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="microphoneAGCEnabled", Tag=0x00000023, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="imageRotation", Tag=0x00000024, Type=typing.Optional[uint]), - ClusterObjectFieldDescriptor(Label="imageFlipHorizontal", Tag=0x00000025, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="imageFlipVertical", Tag=0x00000026, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="localVideoRecordingEnabled", Tag=0x00000027, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="localSnapshotRecordingEnabled", Tag=0x00000028, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="statusLightEnabled", Tag=0x00000029, Type=typing.Optional[bool]), - ClusterObjectFieldDescriptor(Label="statusLightBrightness", Tag=0x0000002A, Type=typing.Optional[Globals.Enums.ThreeLevelAutoEnum]), + ClusterObjectFieldDescriptor(Label="fabricsUsingCamera", Tag=0x0000000E, Type=typing.List[uint]), + ClusterObjectFieldDescriptor(Label="allocatedVideoStreams", Tag=0x0000000F, Type=typing.Optional[typing.List[CameraAvStreamManagement.Structs.VideoStreamStruct]]), + ClusterObjectFieldDescriptor(Label="allocatedAudioStreams", Tag=0x00000010, Type=typing.Optional[typing.List[CameraAvStreamManagement.Structs.AudioStreamStruct]]), + ClusterObjectFieldDescriptor(Label="allocatedSnapshotStreams", Tag=0x00000011, Type=typing.Optional[typing.List[CameraAvStreamManagement.Structs.SnapshotStreamStruct]]), + ClusterObjectFieldDescriptor(Label="rankedVideoStreamPrioritiesList", Tag=0x00000012, Type=typing.Optional[typing.List[CameraAvStreamManagement.Enums.StreamTypeEnum]]), + ClusterObjectFieldDescriptor(Label="softRecordingPrivacyModeEnabled", Tag=0x00000013, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="softLivestreamPrivacyModeEnabled", Tag=0x00000014, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="hardPrivacyModeOn", Tag=0x00000015, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="nightVision", Tag=0x00000016, Type=typing.Optional[CameraAvStreamManagement.Enums.TriStateAutoEnum]), + ClusterObjectFieldDescriptor(Label="nightVisionIllum", Tag=0x00000017, Type=typing.Optional[CameraAvStreamManagement.Enums.TriStateAutoEnum]), + ClusterObjectFieldDescriptor(Label="viewport", Tag=0x00000018, Type=typing.Optional[CameraAvStreamManagement.Structs.ViewportStruct]), + ClusterObjectFieldDescriptor(Label="speakerMuted", Tag=0x00000019, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="speakerVolumeLevel", Tag=0x0000001A, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="speakerMaxLevel", Tag=0x0000001B, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="speakerMinLevel", Tag=0x0000001C, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="microphoneMuted", Tag=0x0000001D, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="microphoneVolumeLevel", Tag=0x0000001E, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="microphoneMaxLevel", Tag=0x0000001F, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="microphoneMinLevel", Tag=0x00000020, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="microphoneAGCEnabled", Tag=0x00000021, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="imageRotation", Tag=0x00000022, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="imageFlipHorizontal", Tag=0x00000023, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="imageFlipVertical", Tag=0x00000024, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="localVideoRecordingEnabled", Tag=0x00000025, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="localSnapshotRecordingEnabled", Tag=0x00000026, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="statusLightEnabled", Tag=0x00000027, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="statusLightBrightness", Tag=0x00000028, Type=typing.Optional[Globals.Enums.ThreeLevelAutoEnum]), ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="attributeList", Tag=0x0000FFFB, Type=typing.List[uint]), @@ -44840,8 +44838,6 @@ def descriptor(cls) -> ClusterObjectDescriptor: maxNetworkBandwidth: uint = 0 currentFrameRate: typing.Optional[uint] = None HDRModeEnabled: typing.Optional[bool] = None - currentVideoCodecs: typing.Optional[typing.List[CameraAvStreamManagement.Enums.VideoCodecEnum]] = None - currentSnapshotConfig: typing.Optional[CameraAvStreamManagement.Structs.SnapshotParamsStruct] = None fabricsUsingCamera: typing.List[uint] = field(default_factory=lambda: []) allocatedVideoStreams: typing.Optional[typing.List[CameraAvStreamManagement.Structs.VideoStreamStruct]] = None allocatedAudioStreams: typing.Optional[typing.List[CameraAvStreamManagement.Structs.AudioStreamStruct]] = None @@ -45294,7 +45290,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ ClusterObjectFieldDescriptor(Label="imageCodec", Tag=0, Type=CameraAvStreamManagement.Enums.ImageCodecEnum), - ClusterObjectFieldDescriptor(Label="frameRate", Tag=1, Type=uint), + ClusterObjectFieldDescriptor(Label="maxFrameRate", Tag=1, Type=uint), ClusterObjectFieldDescriptor(Label="bitRate", Tag=2, Type=uint), ClusterObjectFieldDescriptor(Label="minResolution", Tag=3, Type=CameraAvStreamManagement.Structs.VideoResolutionStruct), ClusterObjectFieldDescriptor(Label="maxResolution", Tag=4, Type=CameraAvStreamManagement.Structs.VideoResolutionStruct), @@ -45302,7 +45298,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ]) imageCodec: CameraAvStreamManagement.Enums.ImageCodecEnum = 0 - frameRate: uint = 0 + maxFrameRate: uint = 0 bitRate: uint = 0 minResolution: CameraAvStreamManagement.Structs.VideoResolutionStruct = field(default_factory=lambda: CameraAvStreamManagement.Structs.VideoResolutionStruct()) maxResolution: CameraAvStreamManagement.Structs.VideoResolutionStruct = field(default_factory=lambda: CameraAvStreamManagement.Structs.VideoResolutionStruct()) @@ -45619,38 +45615,6 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: typing.Optional[bool] = None - @dataclass - class CurrentVideoCodecs(ClusterAttributeDescriptor): - @ChipUtility.classproperty - def cluster_id(cls) -> int: - return 0x00000551 - - @ChipUtility.classproperty - def attribute_id(cls) -> int: - return 0x0000000E - - @ChipUtility.classproperty - def attribute_type(cls) -> ClusterObjectFieldDescriptor: - return ClusterObjectFieldDescriptor(Type=typing.Optional[typing.List[CameraAvStreamManagement.Enums.VideoCodecEnum]]) - - value: typing.Optional[typing.List[CameraAvStreamManagement.Enums.VideoCodecEnum]] = None - - @dataclass - class CurrentSnapshotConfig(ClusterAttributeDescriptor): - @ChipUtility.classproperty - def cluster_id(cls) -> int: - return 0x00000551 - - @ChipUtility.classproperty - def attribute_id(cls) -> int: - return 0x0000000F - - @ChipUtility.classproperty - def attribute_type(cls) -> ClusterObjectFieldDescriptor: - return ClusterObjectFieldDescriptor(Type=typing.Optional[CameraAvStreamManagement.Structs.SnapshotParamsStruct]) - - value: typing.Optional[CameraAvStreamManagement.Structs.SnapshotParamsStruct] = None - @dataclass class FabricsUsingCamera(ClusterAttributeDescriptor): @ChipUtility.classproperty @@ -45659,7 +45623,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000010 + return 0x0000000E @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45675,7 +45639,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000011 + return 0x0000000F @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45691,7 +45655,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000012 + return 0x00000010 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45707,7 +45671,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000013 + return 0x00000011 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45723,7 +45687,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000014 + return 0x00000012 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45739,7 +45703,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000015 + return 0x00000013 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45755,7 +45719,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000016 + return 0x00000014 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45771,7 +45735,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000017 + return 0x00000015 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45787,7 +45751,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000018 + return 0x00000016 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45803,7 +45767,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000019 + return 0x00000017 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45819,7 +45783,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000001A + return 0x00000018 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45835,7 +45799,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000001B + return 0x00000019 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45851,7 +45815,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000001C + return 0x0000001A @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45867,7 +45831,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000001D + return 0x0000001B @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45883,7 +45847,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000001E + return 0x0000001C @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45899,7 +45863,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000001F + return 0x0000001D @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45915,7 +45879,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000020 + return 0x0000001E @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45931,7 +45895,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000021 + return 0x0000001F @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45947,7 +45911,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000022 + return 0x00000020 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45963,7 +45927,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000023 + return 0x00000021 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45979,7 +45943,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000024 + return 0x00000022 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -45995,7 +45959,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000025 + return 0x00000023 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -46011,7 +45975,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000026 + return 0x00000024 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -46027,7 +45991,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000027 + return 0x00000025 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -46043,7 +46007,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000028 + return 0x00000026 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -46059,7 +46023,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x00000029 + return 0x00000027 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: @@ -46075,7 +46039,7 @@ def cluster_id(cls) -> int: @ChipUtility.classproperty def attribute_id(cls) -> int: - return 0x0000002A + return 0x00000028 @ChipUtility.classproperty def attribute_type(cls) -> ClusterObjectFieldDescriptor: diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm index 3f55a10f84..ce5c71d23f 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm @@ -5637,12 +5637,6 @@ static BOOL AttributeIsSpecifiedInCameraAVStreamManagementCluster(AttributeId aA case Attributes::HDRModeEnabled::Id: { return YES; } - case Attributes::CurrentVideoCodecs::Id: { - return YES; - } - case Attributes::CurrentSnapshotConfig::Id: { - return YES; - } case Attributes::FabricsUsingCamera::Id: { return YES; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index 571793a7ed..975c3b63f4 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -17210,48 +17210,6 @@ static id _Nullable DecodeAttributeValueForCameraAVStreamManagementCluster(Attri value = [NSNumber numberWithBool:cppValue]; return value; } - case Attributes::CurrentVideoCodecs::Id: { - using TypeInfo = Attributes::CurrentVideoCodecs::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - auto iter_0 = cppValue.begin(); - while (iter_0.Next()) { - auto & entry_0 = iter_0.GetValue(); - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0)]; - [array_0 addObject:newElement_0]; - } - CHIP_ERROR err = iter_0.GetStatus(); - if (err != CHIP_NO_ERROR) { - *aError = err; - return nil; - } - value = array_0; - } - return value; - } - case Attributes::CurrentSnapshotConfig::Id: { - using TypeInfo = Attributes::CurrentSnapshotConfig::TypeInfo; - TypeInfo::DecodableType cppValue; - *aError = DataModel::Decode(aReader, cppValue); - if (*aError != CHIP_NO_ERROR) { - return nil; - } - MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nonnull value; - value = [MTRCameraAVStreamManagementClusterSnapshotParamsStruct new]; - value.resolution = [MTRCameraAVStreamManagementClusterVideoResolutionStruct new]; - value.resolution.width = [NSNumber numberWithUnsignedShort:cppValue.resolution.width]; - value.resolution.height = [NSNumber numberWithUnsignedShort:cppValue.resolution.height]; - value.maxFrameRate = [NSNumber numberWithUnsignedShort:cppValue.maxFrameRate]; - value.imageCodec = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue.imageCodec)]; - return value; - } case Attributes::FabricsUsingCamera::Id: { using TypeInfo = Attributes::FabricsUsingCamera::TypeInfo; TypeInfo::DecodableType cppValue; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index 92212cc373..32c79ee20f 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -14286,18 +14286,6 @@ MTR_PROVISIONALLY_AVAILABLE reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeHDRModeEnabledWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)readAttributeCurrentVideoCodecsWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)subscribeAttributeCurrentVideoCodecsWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeCurrentVideoCodecsWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - -- (void)readAttributeCurrentSnapshotConfigWithCompletion:(void (^)(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)subscribeAttributeCurrentSnapshotConfigWithParams:(MTRSubscribeParams *)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; -+ (void)readAttributeCurrentSnapshotConfigWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - - (void)readAttributeFabricsUsingCameraWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeFabricsUsingCameraWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished @@ -14323,8 +14311,6 @@ MTR_PROVISIONALLY_AVAILABLE + (void)readAttributeAllocatedSnapshotStreamsWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)readAttributeRankedVideoStreamPrioritiesListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSArray * _Nonnull)value completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSArray * _Nonnull)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeRankedVideoStreamPrioritiesListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index 07e00f7088..ea02951aa5 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -98867,78 +98867,6 @@ + (void)readAttributeHDRModeEnabledWithClusterStateCache:(MTRClusterStateCacheCo completion:completion]; } -- (void)readAttributeCurrentVideoCodecsWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - using TypeInfo = CameraAvStreamManagement::Attributes::CurrentVideoCodecs::TypeInfo; - [self.device _readKnownAttributeWithEndpointID:self.endpointID - clusterID:@(TypeInfo::GetClusterId()) - attributeID:@(TypeInfo::GetAttributeId()) - params:nil - queue:self.callbackQueue - completion:completion]; -} - -- (void)subscribeAttributeCurrentVideoCodecsWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = CameraAvStreamManagement::Attributes::CurrentVideoCodecs::TypeInfo; - [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID - clusterID:@(TypeInfo::GetClusterId()) - attributeID:@(TypeInfo::GetAttributeId()) - params:params - queue:self.callbackQueue - reportHandler:reportHandler - subscriptionEstablished:subscriptionEstablished]; -} - -+ (void)readAttributeCurrentVideoCodecsWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion -{ - using TypeInfo = CameraAvStreamManagement::Attributes::CurrentVideoCodecs::TypeInfo; - [clusterStateCacheContainer - _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) - clusterID:TypeInfo::GetClusterId() - attributeID:TypeInfo::GetAttributeId() - queue:queue - completion:completion]; -} - -- (void)readAttributeCurrentSnapshotConfigWithCompletion:(void (^)(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error))completion -{ - using TypeInfo = CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::TypeInfo; - [self.device _readKnownAttributeWithEndpointID:self.endpointID - clusterID:@(TypeInfo::GetClusterId()) - attributeID:@(TypeInfo::GetAttributeId()) - params:nil - queue:self.callbackQueue - completion:completion]; -} - -- (void)subscribeAttributeCurrentSnapshotConfigWithParams:(MTRSubscribeParams * _Nonnull)params - subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished - reportHandler:(void (^)(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error))reportHandler -{ - using TypeInfo = CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::TypeInfo; - [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID - clusterID:@(TypeInfo::GetClusterId()) - attributeID:@(TypeInfo::GetAttributeId()) - params:params - queue:self.callbackQueue - reportHandler:reportHandler - subscriptionEstablished:subscriptionEstablished]; -} - -+ (void)readAttributeCurrentSnapshotConfigWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error))completion -{ - using TypeInfo = CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::TypeInfo; - [clusterStateCacheContainer - _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) - clusterID:TypeInfo::GetClusterId() - attributeID:TypeInfo::GetAttributeId() - queue:queue - completion:completion]; -} - - (void)readAttributeFabricsUsingCameraWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion { using TypeInfo = CameraAvStreamManagement::Attributes::FabricsUsingCamera::TypeInfo; @@ -99094,55 +99022,6 @@ - (void)readAttributeRankedVideoStreamPrioritiesListWithCompletion:(void (^)(NSA completion:completion]; } -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSArray * _Nonnull)value completion:(MTRStatusCompletion)completion -{ - [self writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSArray * _Nonnull) value params:nil completion:completion]; -} -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSArray * _Nonnull)value params:(MTRWriteParams * _Nullable)params completion:(MTRStatusCompletion)completion -{ - // Make a copy of params before we go async. - params = [params copy]; - value = [value copy]; - - auto * bridge = new MTRDefaultSuccessCallbackBridge(self.callbackQueue, ^(id _Nullable ignored, NSError * _Nullable error) { completion(error); }, ^(ExchangeManager & exchangeManager, const SessionHandle & session, DefaultSuccessCallbackType successCb, MTRErrorCallback failureCb, MTRCallbackBridgeBase * bridge) { - chip::Optional timedWriteTimeout; - if (params != nil) { - if (params.timedWriteTimeout != nil){ - timedWriteTimeout.SetValue(params.timedWriteTimeout.unsignedShortValue); - } - } - - ListFreer listFreer; - using TypeInfo = CameraAvStreamManagement::Attributes::RankedVideoStreamPrioritiesList::TypeInfo; - TypeInfo::Type cppValue; - { - using ListType_0 = std::remove_reference_t; - using ListMemberType_0 = ListMemberTypeGetter::Type; - if (value.count != 0) { - auto * listHolder_0 = new ListHolder(value.count); - if (listHolder_0 == nullptr || listHolder_0->mList == nullptr) { - return CHIP_ERROR_INVALID_ARGUMENT; - } - listFreer.add(listHolder_0); - for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSNumber class]] ) { - // Wrong kind of value. - return CHIP_ERROR_INVALID_ARGUMENT; - } - auto element_0 = (NSNumber *)value[i_0]; - listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); - } - cppValue = ListType_0(listHolder_0->mList, value.count); - } else { - cppValue = ListType_0(); - } - } - - chip::Controller::ClusterBase cppCluster(exchangeManager, session, self.endpointID.unsignedShortValue); - return cppCluster.WriteAttribute(cppValue, bridge, successCb, failureCb, timedWriteTimeout); }); - std::move(*bridge).DispatchAction(self.device); -} - - (void)subscribeAttributeRankedVideoStreamPrioritiesListWithParams:(MTRSubscribeParams * _Nonnull)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished reportHandler:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))reportHandler diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index 7587e25a24..e58a3a60d8 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -4649,35 +4649,33 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMaxNetworkBandwidthID MTR_PROVISIONALLY_AVAILABLE = 0x0000000B, MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentFrameRateID MTR_PROVISIONALLY_AVAILABLE = 0x0000000C, MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeHDRModeEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x0000000D, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentVideoCodecsID MTR_PROVISIONALLY_AVAILABLE = 0x0000000E, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentSnapshotConfigID MTR_PROVISIONALLY_AVAILABLE = 0x0000000F, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeFabricsUsingCameraID MTR_PROVISIONALLY_AVAILABLE = 0x00000010, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAllocatedVideoStreamsID MTR_PROVISIONALLY_AVAILABLE = 0x00000011, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAllocatedAudioStreamsID MTR_PROVISIONALLY_AVAILABLE = 0x00000012, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAllocatedSnapshotStreamsID MTR_PROVISIONALLY_AVAILABLE = 0x00000013, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeRankedVideoStreamPrioritiesListID MTR_PROVISIONALLY_AVAILABLE = 0x00000014, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSoftRecordingPrivacyModeEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000015, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSoftLivestreamPrivacyModeEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000016, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeHardPrivacyModeOnID MTR_PROVISIONALLY_AVAILABLE = 0x00000017, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeNightVisionID MTR_PROVISIONALLY_AVAILABLE = 0x00000018, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeNightVisionIllumID MTR_PROVISIONALLY_AVAILABLE = 0x00000019, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeViewportID MTR_PROVISIONALLY_AVAILABLE = 0x0000001A, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerMutedID MTR_PROVISIONALLY_AVAILABLE = 0x0000001B, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerVolumeLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001C, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerMaxLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001D, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerMinLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001E, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneMutedID MTR_PROVISIONALLY_AVAILABLE = 0x0000001F, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneVolumeLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000020, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneMaxLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000021, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneMinLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000022, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneAGCEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000023, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeImageRotationID MTR_PROVISIONALLY_AVAILABLE = 0x00000024, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeImageFlipHorizontalID MTR_PROVISIONALLY_AVAILABLE = 0x00000025, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeImageFlipVerticalID MTR_PROVISIONALLY_AVAILABLE = 0x00000026, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeLocalVideoRecordingEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000027, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeLocalSnapshotRecordingEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000028, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeStatusLightEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000029, - MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeStatusLightBrightnessID MTR_PROVISIONALLY_AVAILABLE = 0x0000002A, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeFabricsUsingCameraID MTR_PROVISIONALLY_AVAILABLE = 0x0000000E, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAllocatedVideoStreamsID MTR_PROVISIONALLY_AVAILABLE = 0x0000000F, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAllocatedAudioStreamsID MTR_PROVISIONALLY_AVAILABLE = 0x00000010, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAllocatedSnapshotStreamsID MTR_PROVISIONALLY_AVAILABLE = 0x00000011, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeRankedVideoStreamPrioritiesListID MTR_PROVISIONALLY_AVAILABLE = 0x00000012, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSoftRecordingPrivacyModeEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000013, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSoftLivestreamPrivacyModeEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000014, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeHardPrivacyModeOnID MTR_PROVISIONALLY_AVAILABLE = 0x00000015, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeNightVisionID MTR_PROVISIONALLY_AVAILABLE = 0x00000016, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeNightVisionIllumID MTR_PROVISIONALLY_AVAILABLE = 0x00000017, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeViewportID MTR_PROVISIONALLY_AVAILABLE = 0x00000018, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerMutedID MTR_PROVISIONALLY_AVAILABLE = 0x00000019, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerVolumeLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001A, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerMaxLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001B, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSpeakerMinLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001C, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneMutedID MTR_PROVISIONALLY_AVAILABLE = 0x0000001D, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneVolumeLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001E, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneMaxLevelID MTR_PROVISIONALLY_AVAILABLE = 0x0000001F, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneMinLevelID MTR_PROVISIONALLY_AVAILABLE = 0x00000020, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeMicrophoneAGCEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000021, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeImageRotationID MTR_PROVISIONALLY_AVAILABLE = 0x00000022, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeImageFlipHorizontalID MTR_PROVISIONALLY_AVAILABLE = 0x00000023, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeImageFlipVerticalID MTR_PROVISIONALLY_AVAILABLE = 0x00000024, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeLocalVideoRecordingEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000025, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeLocalSnapshotRecordingEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000026, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeStatusLightEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000027, + MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeStatusLightBrightnessID MTR_PROVISIONALLY_AVAILABLE = 0x00000028, MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeAttributeListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAttributeListID, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm index 0791fc4952..96b2c0cd3b 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm @@ -7783,14 +7783,6 @@ result = @"HDRModeEnabled"; break; - case MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentVideoCodecsID: - result = @"CurrentVideoCodecs"; - break; - - case MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentSnapshotConfigID: - result = @"CurrentSnapshotConfig"; - break; - case MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeFabricsUsingCameraID: result = @"FabricsUsingCamera"; break; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index 4c28d0ddd3..9babe0a625 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -6674,10 +6674,6 @@ MTR_PROVISIONALLY_AVAILABLE - (void)writeAttributeHDRModeEnabledWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_PROVISIONALLY_AVAILABLE; - (void)writeAttributeHDRModeEnabledWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (NSDictionary * _Nullable)readAttributeCurrentVideoCodecsWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - -- (NSDictionary * _Nullable)readAttributeCurrentSnapshotConfigWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - - (NSDictionary * _Nullable)readAttributeFabricsUsingCameraWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeAllocatedVideoStreamsWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; @@ -6687,8 +6683,6 @@ MTR_PROVISIONALLY_AVAILABLE - (NSDictionary * _Nullable)readAttributeAllocatedSnapshotStreamsWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeRankedVideoStreamPrioritiesListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_PROVISIONALLY_AVAILABLE; -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeSoftRecordingPrivacyModeEnabledWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (void)writeAttributeSoftRecordingPrivacyModeEnabledWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 500aa41148..1d6828dedd 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -19397,16 +19397,6 @@ - (void)writeAttributeHDRModeEnabledWithValue:(NSDictionary *)da [self.device writeAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeHDRModeEnabledID) value:dataValueDictionary expectedValueInterval:expectedValueIntervalMs timedWriteTimeout:timedWriteTimeout]; } -- (NSDictionary * _Nullable)readAttributeCurrentVideoCodecsWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentVideoCodecsID) params:params]; -} - -- (NSDictionary * _Nullable)readAttributeCurrentSnapshotConfigWithParams:(MTRReadParams * _Nullable)params -{ - return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeCurrentSnapshotConfigID) params:params]; -} - - (NSDictionary * _Nullable)readAttributeFabricsUsingCameraWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeFabricsUsingCameraID) params:params]; @@ -19432,17 +19422,6 @@ - (void)writeAttributeHDRModeEnabledWithValue:(NSDictionary *)da return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeRankedVideoStreamPrioritiesListID) params:params]; } -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs -{ - [self writeAttributeRankedVideoStreamPrioritiesListWithValue:dataValueDictionary expectedValueInterval:expectedValueIntervalMs params:nil]; -} -- (void)writeAttributeRankedVideoStreamPrioritiesListWithValue:(NSDictionary *)dataValueDictionary expectedValueInterval:(NSNumber *)expectedValueIntervalMs params:(MTRWriteParams * _Nullable)params -{ - NSNumber * timedWriteTimeout = params.timedWriteTimeout; - - [self.device writeAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeRankedVideoStreamPrioritiesListID) value:dataValueDictionary expectedValueInterval:expectedValueIntervalMs timedWriteTimeout:timedWriteTimeout]; -} - - (NSDictionary * _Nullable)readAttributeSoftRecordingPrivacyModeEnabledWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeCameraAVStreamManagementID) attributeID:@(MTRAttributeIDTypeClusterCameraAVStreamManagementAttributeSoftRecordingPrivacyModeEnabledID) params:params]; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index c6dbb8e975..573d6581ce 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -11226,7 +11226,7 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull imageCodec MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nonnull frameRate MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull maxFrameRate MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull bitRate MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index b737f253cb..6d8ddd6091 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -32619,7 +32619,7 @@ - (instancetype)init _imageCodec = @(0); - _frameRate = @(0); + _maxFrameRate = @(0); _bitRate = @(0); @@ -32639,7 +32639,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; auto other = [[MTRCameraAVStreamManagementClusterSnapshotStreamAllocateParams alloc] init]; other.imageCodec = self.imageCodec; - other.frameRate = self.frameRate; + other.maxFrameRate = self.maxFrameRate; other.bitRate = self.bitRate; other.minResolution = self.minResolution; other.maxResolution = self.maxResolution; @@ -32652,7 +32652,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: imageCodec:%@; frameRate:%@; bitRate:%@; minResolution:%@; maxResolution:%@; quality:%@; >", NSStringFromClass([self class]), _imageCodec, _frameRate, _bitRate, _minResolution, _maxResolution, _quality]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: imageCodec:%@; maxFrameRate:%@; bitRate:%@; minResolution:%@; maxResolution:%@; quality:%@; >", NSStringFromClass([self class]), _imageCodec, _maxFrameRate, _bitRate, _minResolution, _maxResolution, _quality]; return descriptionString; } @@ -32668,7 +32668,7 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader encodableStruct.imageCodec = static_cast>(self.imageCodec.unsignedCharValue); } { - encodableStruct.frameRate = self.frameRate.unsignedShortValue; + encodableStruct.maxFrameRate = self.maxFrameRate.unsignedShortValue; } { encodableStruct.bitRate = self.bitRate.unsignedIntValue; diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index f2c2ea2ef5..4879ae5213 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -29749,7 +29749,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kImageCodec), imageCodec); - encoder.Encode(to_underlying(Fields::kFrameRate), frameRate); + encoder.Encode(to_underlying(Fields::kMaxFrameRate), maxFrameRate); encoder.Encode(to_underlying(Fields::kBitRate), bitRate); encoder.Encode(to_underlying(Fields::kMinResolution), minResolution); encoder.Encode(to_underlying(Fields::kMaxResolution), maxResolution); @@ -29775,9 +29775,9 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, imageCodec); } - else if (__context_tag == to_underlying(Fields::kFrameRate)) + else if (__context_tag == to_underlying(Fields::kMaxFrameRate)) { - err = DataModel::Decode(reader, frameRate); + err = DataModel::Decode(reader, maxFrameRate); } else if (__context_tag == to_underlying(Fields::kBitRate)) { @@ -30023,10 +30023,6 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre return DataModel::Decode(reader, currentFrameRate); case Attributes::HDRModeEnabled::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, HDRModeEnabled); - case Attributes::CurrentVideoCodecs::TypeInfo::GetAttributeId(): - return DataModel::Decode(reader, currentVideoCodecs); - case Attributes::CurrentSnapshotConfig::TypeInfo::GetAttributeId(): - return DataModel::Decode(reader, currentSnapshotConfig); case Attributes::FabricsUsingCamera::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, fabricsUsingCamera); case Attributes::AllocatedVideoStreams::TypeInfo::GetAttributeId(): diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index 35e2682528..2357a87dd9 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -41542,7 +41542,7 @@ namespace SnapshotStreamAllocate { enum class Fields : uint8_t { kImageCodec = 0, - kFrameRate = 1, + kMaxFrameRate = 1, kBitRate = 2, kMinResolution = 3, kMaxResolution = 4, @@ -41557,7 +41557,7 @@ struct Type static constexpr ClusterId GetClusterId() { return Clusters::CameraAvStreamManagement::Id; } ImageCodecEnum imageCodec = static_cast(0); - uint16_t frameRate = static_cast(0); + uint16_t maxFrameRate = static_cast(0); uint32_t bitRate = static_cast(0); Structs::VideoResolutionStruct::Type minResolution; Structs::VideoResolutionStruct::Type maxResolution; @@ -41577,7 +41577,7 @@ struct DecodableType static constexpr ClusterId GetClusterId() { return Clusters::CameraAvStreamManagement::Id; } ImageCodecEnum imageCodec = static_cast(0); - uint16_t frameRate = static_cast(0); + uint16_t maxFrameRate = static_cast(0); uint32_t bitRate = static_cast(0); Structs::VideoResolutionStruct::DecodableType minResolution; Structs::VideoResolutionStruct::DecodableType maxResolution; @@ -41932,31 +41932,6 @@ struct TypeInfo static constexpr bool MustUseTimedWrite() { return false; } }; } // namespace HDRModeEnabled -namespace CurrentVideoCodecs { -struct TypeInfo -{ - using Type = chip::app::DataModel::List; - using DecodableType = chip::app::DataModel::DecodableList; - using DecodableArgType = - const chip::app::DataModel::DecodableList &; - - static constexpr ClusterId GetClusterId() { return Clusters::CameraAvStreamManagement::Id; } - static constexpr AttributeId GetAttributeId() { return Attributes::CurrentVideoCodecs::Id; } - static constexpr bool MustUseTimedWrite() { return false; } -}; -} // namespace CurrentVideoCodecs -namespace CurrentSnapshotConfig { -struct TypeInfo -{ - using Type = chip::app::Clusters::CameraAvStreamManagement::Structs::SnapshotParamsStruct::Type; - using DecodableType = chip::app::Clusters::CameraAvStreamManagement::Structs::SnapshotParamsStruct::DecodableType; - using DecodableArgType = const chip::app::Clusters::CameraAvStreamManagement::Structs::SnapshotParamsStruct::DecodableType &; - - static constexpr ClusterId GetClusterId() { return Clusters::CameraAvStreamManagement::Id; } - static constexpr AttributeId GetAttributeId() { return Attributes::CurrentSnapshotConfig::Id; } - static constexpr bool MustUseTimedWrite() { return false; } -}; -} // namespace CurrentSnapshotConfig namespace FabricsUsingCamera { struct TypeInfo { @@ -42343,8 +42318,6 @@ struct TypeInfo Attributes::MaxNetworkBandwidth::TypeInfo::DecodableType maxNetworkBandwidth = static_cast(0); Attributes::CurrentFrameRate::TypeInfo::DecodableType currentFrameRate = static_cast(0); Attributes::HDRModeEnabled::TypeInfo::DecodableType HDRModeEnabled = static_cast(0); - Attributes::CurrentVideoCodecs::TypeInfo::DecodableType currentVideoCodecs; - Attributes::CurrentSnapshotConfig::TypeInfo::DecodableType currentSnapshotConfig; Attributes::FabricsUsingCamera::TypeInfo::DecodableType fabricsUsingCamera; Attributes::AllocatedVideoStreams::TypeInfo::DecodableType allocatedVideoStreams; Attributes::AllocatedAudioStreams::TypeInfo::DecodableType allocatedAudioStreams; diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h index e0fa3a25fd..5d12daa856 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h @@ -6922,120 +6922,112 @@ namespace HDRModeEnabled { static constexpr AttributeId Id = 0x0000000D; } // namespace HDRModeEnabled -namespace CurrentVideoCodecs { -static constexpr AttributeId Id = 0x0000000E; -} // namespace CurrentVideoCodecs - -namespace CurrentSnapshotConfig { -static constexpr AttributeId Id = 0x0000000F; -} // namespace CurrentSnapshotConfig - namespace FabricsUsingCamera { -static constexpr AttributeId Id = 0x00000010; +static constexpr AttributeId Id = 0x0000000E; } // namespace FabricsUsingCamera namespace AllocatedVideoStreams { -static constexpr AttributeId Id = 0x00000011; +static constexpr AttributeId Id = 0x0000000F; } // namespace AllocatedVideoStreams namespace AllocatedAudioStreams { -static constexpr AttributeId Id = 0x00000012; +static constexpr AttributeId Id = 0x00000010; } // namespace AllocatedAudioStreams namespace AllocatedSnapshotStreams { -static constexpr AttributeId Id = 0x00000013; +static constexpr AttributeId Id = 0x00000011; } // namespace AllocatedSnapshotStreams namespace RankedVideoStreamPrioritiesList { -static constexpr AttributeId Id = 0x00000014; +static constexpr AttributeId Id = 0x00000012; } // namespace RankedVideoStreamPrioritiesList namespace SoftRecordingPrivacyModeEnabled { -static constexpr AttributeId Id = 0x00000015; +static constexpr AttributeId Id = 0x00000013; } // namespace SoftRecordingPrivacyModeEnabled namespace SoftLivestreamPrivacyModeEnabled { -static constexpr AttributeId Id = 0x00000016; +static constexpr AttributeId Id = 0x00000014; } // namespace SoftLivestreamPrivacyModeEnabled namespace HardPrivacyModeOn { -static constexpr AttributeId Id = 0x00000017; +static constexpr AttributeId Id = 0x00000015; } // namespace HardPrivacyModeOn namespace NightVision { -static constexpr AttributeId Id = 0x00000018; +static constexpr AttributeId Id = 0x00000016; } // namespace NightVision namespace NightVisionIllum { -static constexpr AttributeId Id = 0x00000019; +static constexpr AttributeId Id = 0x00000017; } // namespace NightVisionIllum namespace Viewport { -static constexpr AttributeId Id = 0x0000001A; +static constexpr AttributeId Id = 0x00000018; } // namespace Viewport namespace SpeakerMuted { -static constexpr AttributeId Id = 0x0000001B; +static constexpr AttributeId Id = 0x00000019; } // namespace SpeakerMuted namespace SpeakerVolumeLevel { -static constexpr AttributeId Id = 0x0000001C; +static constexpr AttributeId Id = 0x0000001A; } // namespace SpeakerVolumeLevel namespace SpeakerMaxLevel { -static constexpr AttributeId Id = 0x0000001D; +static constexpr AttributeId Id = 0x0000001B; } // namespace SpeakerMaxLevel namespace SpeakerMinLevel { -static constexpr AttributeId Id = 0x0000001E; +static constexpr AttributeId Id = 0x0000001C; } // namespace SpeakerMinLevel namespace MicrophoneMuted { -static constexpr AttributeId Id = 0x0000001F; +static constexpr AttributeId Id = 0x0000001D; } // namespace MicrophoneMuted namespace MicrophoneVolumeLevel { -static constexpr AttributeId Id = 0x00000020; +static constexpr AttributeId Id = 0x0000001E; } // namespace MicrophoneVolumeLevel namespace MicrophoneMaxLevel { -static constexpr AttributeId Id = 0x00000021; +static constexpr AttributeId Id = 0x0000001F; } // namespace MicrophoneMaxLevel namespace MicrophoneMinLevel { -static constexpr AttributeId Id = 0x00000022; +static constexpr AttributeId Id = 0x00000020; } // namespace MicrophoneMinLevel namespace MicrophoneAGCEnabled { -static constexpr AttributeId Id = 0x00000023; +static constexpr AttributeId Id = 0x00000021; } // namespace MicrophoneAGCEnabled namespace ImageRotation { -static constexpr AttributeId Id = 0x00000024; +static constexpr AttributeId Id = 0x00000022; } // namespace ImageRotation namespace ImageFlipHorizontal { -static constexpr AttributeId Id = 0x00000025; +static constexpr AttributeId Id = 0x00000023; } // namespace ImageFlipHorizontal namespace ImageFlipVertical { -static constexpr AttributeId Id = 0x00000026; +static constexpr AttributeId Id = 0x00000024; } // namespace ImageFlipVertical namespace LocalVideoRecordingEnabled { -static constexpr AttributeId Id = 0x00000027; +static constexpr AttributeId Id = 0x00000025; } // namespace LocalVideoRecordingEnabled namespace LocalSnapshotRecordingEnabled { -static constexpr AttributeId Id = 0x00000028; +static constexpr AttributeId Id = 0x00000026; } // namespace LocalSnapshotRecordingEnabled namespace StatusLightEnabled { -static constexpr AttributeId Id = 0x00000029; +static constexpr AttributeId Id = 0x00000027; } // namespace StatusLightEnabled namespace StatusLightBrightness { -static constexpr AttributeId Id = 0x0000002A; +static constexpr AttributeId Id = 0x00000028; } // namespace StatusLightBrightness namespace GeneratedCommandList { diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 3fca885315..b0c00980d3 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -13736,35 +13736,33 @@ class ZoneManagementRemoveZone : public ClusterCommand | * MaxNetworkBandwidth | 0x000B | | * CurrentFrameRate | 0x000C | | * HDRModeEnabled | 0x000D | -| * CurrentVideoCodecs | 0x000E | -| * CurrentSnapshotConfig | 0x000F | -| * FabricsUsingCamera | 0x0010 | -| * AllocatedVideoStreams | 0x0011 | -| * AllocatedAudioStreams | 0x0012 | -| * AllocatedSnapshotStreams | 0x0013 | -| * RankedVideoStreamPrioritiesList | 0x0014 | -| * SoftRecordingPrivacyModeEnabled | 0x0015 | -| * SoftLivestreamPrivacyModeEnabled | 0x0016 | -| * HardPrivacyModeOn | 0x0017 | -| * NightVision | 0x0018 | -| * NightVisionIllum | 0x0019 | -| * Viewport | 0x001A | -| * SpeakerMuted | 0x001B | -| * SpeakerVolumeLevel | 0x001C | -| * SpeakerMaxLevel | 0x001D | -| * SpeakerMinLevel | 0x001E | -| * MicrophoneMuted | 0x001F | -| * MicrophoneVolumeLevel | 0x0020 | -| * MicrophoneMaxLevel | 0x0021 | -| * MicrophoneMinLevel | 0x0022 | -| * MicrophoneAGCEnabled | 0x0023 | -| * ImageRotation | 0x0024 | -| * ImageFlipHorizontal | 0x0025 | -| * ImageFlipVertical | 0x0026 | -| * LocalVideoRecordingEnabled | 0x0027 | -| * LocalSnapshotRecordingEnabled | 0x0028 | -| * StatusLightEnabled | 0x0029 | -| * StatusLightBrightness | 0x002A | +| * FabricsUsingCamera | 0x000E | +| * AllocatedVideoStreams | 0x000F | +| * AllocatedAudioStreams | 0x0010 | +| * AllocatedSnapshotStreams | 0x0011 | +| * RankedVideoStreamPrioritiesList | 0x0012 | +| * SoftRecordingPrivacyModeEnabled | 0x0013 | +| * SoftLivestreamPrivacyModeEnabled | 0x0014 | +| * HardPrivacyModeOn | 0x0015 | +| * NightVision | 0x0016 | +| * NightVisionIllum | 0x0017 | +| * Viewport | 0x0018 | +| * SpeakerMuted | 0x0019 | +| * SpeakerVolumeLevel | 0x001A | +| * SpeakerMaxLevel | 0x001B | +| * SpeakerMinLevel | 0x001C | +| * MicrophoneMuted | 0x001D | +| * MicrophoneVolumeLevel | 0x001E | +| * MicrophoneMaxLevel | 0x001F | +| * MicrophoneMinLevel | 0x0020 | +| * MicrophoneAGCEnabled | 0x0021 | +| * ImageRotation | 0x0022 | +| * ImageFlipHorizontal | 0x0023 | +| * ImageFlipVertical | 0x0024 | +| * LocalVideoRecordingEnabled | 0x0025 | +| * LocalSnapshotRecordingEnabled | 0x0026 | +| * StatusLightEnabled | 0x0027 | +| * StatusLightBrightness | 0x0028 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * AttributeList | 0xFFFB | @@ -14004,7 +14002,7 @@ class CameraAvStreamManagementSnapshotStreamAllocate : public ClusterCommand mComplex_MaxResolution(&mRequest.maxResolution) { AddArgument("ImageCodec", 0, UINT8_MAX, &mRequest.imageCodec); - AddArgument("FrameRate", 0, UINT16_MAX, &mRequest.frameRate); + AddArgument("MaxFrameRate", 0, UINT16_MAX, &mRequest.maxFrameRate); AddArgument("BitRate", 0, UINT32_MAX, &mRequest.bitRate); AddArgument("MinResolution", &mComplex_MinResolution); AddArgument("MaxResolution", &mComplex_MaxResolution); @@ -26768,8 +26766,6 @@ void registerClusterCameraAvStreamManagement(Commands & commands, CredentialIssu make_unique(Id, "max-network-bandwidth", Attributes::MaxNetworkBandwidth::Id, credsIssuerConfig), // make_unique(Id, "current-frame-rate", Attributes::CurrentFrameRate::Id, credsIssuerConfig), // make_unique(Id, "hdrmode-enabled", Attributes::HDRModeEnabled::Id, credsIssuerConfig), // - make_unique(Id, "current-video-codecs", Attributes::CurrentVideoCodecs::Id, credsIssuerConfig), // - make_unique(Id, "current-snapshot-config", Attributes::CurrentSnapshotConfig::Id, credsIssuerConfig), // make_unique(Id, "fabrics-using-camera", Attributes::FabricsUsingCamera::Id, credsIssuerConfig), // make_unique(Id, "allocated-video-streams", Attributes::AllocatedVideoStreams::Id, credsIssuerConfig), // make_unique(Id, "allocated-audio-streams", Attributes::AllocatedAudioStreams::Id, credsIssuerConfig), // @@ -26844,12 +26840,6 @@ void registerClusterCameraAvStreamManagement(Commands & commands, CredentialIssu WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>(Id, "hdrmode-enabled", 0, 1, Attributes::HDRModeEnabled::Id, WriteCommandType::kWrite, credsIssuerConfig), // - make_unique>>( - Id, "current-video-codecs", Attributes::CurrentVideoCodecs::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // - make_unique>( - Id, "current-snapshot-config", Attributes::CurrentSnapshotConfig::Id, WriteCommandType::kForceWrite, - credsIssuerConfig), // make_unique>>( Id, "fabrics-using-camera", Attributes::FabricsUsingCamera::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>>( - Id, "ranked-video-stream-priorities-list", Attributes::RankedVideoStreamPrioritiesList::Id, WriteCommandType::kWrite, - credsIssuerConfig), // + Id, "ranked-video-stream-priorities-list", Attributes::RankedVideoStreamPrioritiesList::Id, + WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>(Id, "soft-recording-privacy-mode-enabled", 0, 1, Attributes::SoftRecordingPrivacyModeEnabled::Id, WriteCommandType::kWrite, credsIssuerConfig), // @@ -26947,8 +26937,6 @@ void registerClusterCameraAvStreamManagement(Commands & commands, CredentialIssu make_unique(Id, "max-network-bandwidth", Attributes::MaxNetworkBandwidth::Id, credsIssuerConfig), // make_unique(Id, "current-frame-rate", Attributes::CurrentFrameRate::Id, credsIssuerConfig), // make_unique(Id, "hdrmode-enabled", Attributes::HDRModeEnabled::Id, credsIssuerConfig), // - make_unique(Id, "current-video-codecs", Attributes::CurrentVideoCodecs::Id, credsIssuerConfig), // - make_unique(Id, "current-snapshot-config", Attributes::CurrentSnapshotConfig::Id, credsIssuerConfig), // make_unique(Id, "fabrics-using-camera", Attributes::FabricsUsingCamera::Id, credsIssuerConfig), // make_unique(Id, "allocated-video-streams", Attributes::AllocatedVideoStreams::Id, credsIssuerConfig), // make_unique(Id, "allocated-audio-streams", Attributes::AllocatedAudioStreams::Id, credsIssuerConfig), // diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index 6fb87819ce..1ea513ea1d 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -18563,16 +18563,6 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("HDRModeEnabled", 1, value); } - case CameraAvStreamManagement::Attributes::CurrentVideoCodecs::Id: { - chip::app::DataModel::DecodableList value; - ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); - return DataModelLogger::LogValue("CurrentVideoCodecs", 1, value); - } - case CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::Id: { - chip::app::Clusters::CameraAvStreamManagement::Structs::SnapshotParamsStruct::DecodableType value; - ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); - return DataModelLogger::LogValue("CurrentSnapshotConfig", 1, value); - } case CameraAvStreamManagement::Attributes::FabricsUsingCamera::Id: { chip::app::DataModel::DecodableList value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp index 753378db6f..3977ee180b 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/EntryToText.cpp @@ -4197,10 +4197,6 @@ char const * AttributeIdToText(chip::ClusterId cluster, chip::AttributeId id) return "CurrentFrameRate"; case chip::app::Clusters::CameraAvStreamManagement::Attributes::HDRModeEnabled::Id: return "HDRModeEnabled"; - case chip::app::Clusters::CameraAvStreamManagement::Attributes::CurrentVideoCodecs::Id: - return "CurrentVideoCodecs"; - case chip::app::Clusters::CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::Id: - return "CurrentSnapshotConfig"; case chip::app::Clusters::CameraAvStreamManagement::Attributes::FabricsUsingCamera::Id: return "FabricsUsingCamera"; case chip::app::Clusters::CameraAvStreamManagement::Attributes::AllocatedVideoStreams::Id: diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 6e8b57d2d8..2d9b737038 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -150659,35 +150659,33 @@ class SubscribeAttributeZoneManagementClusterRevision : public SubscribeAttribut | * MaxNetworkBandwidth | 0x000B | | * CurrentFrameRate | 0x000C | | * HDRModeEnabled | 0x000D | -| * CurrentVideoCodecs | 0x000E | -| * CurrentSnapshotConfig | 0x000F | -| * FabricsUsingCamera | 0x0010 | -| * AllocatedVideoStreams | 0x0011 | -| * AllocatedAudioStreams | 0x0012 | -| * AllocatedSnapshotStreams | 0x0013 | -| * RankedVideoStreamPrioritiesList | 0x0014 | -| * SoftRecordingPrivacyModeEnabled | 0x0015 | -| * SoftLivestreamPrivacyModeEnabled | 0x0016 | -| * HardPrivacyModeOn | 0x0017 | -| * NightVision | 0x0018 | -| * NightVisionIllum | 0x0019 | -| * Viewport | 0x001A | -| * SpeakerMuted | 0x001B | -| * SpeakerVolumeLevel | 0x001C | -| * SpeakerMaxLevel | 0x001D | -| * SpeakerMinLevel | 0x001E | -| * MicrophoneMuted | 0x001F | -| * MicrophoneVolumeLevel | 0x0020 | -| * MicrophoneMaxLevel | 0x0021 | -| * MicrophoneMinLevel | 0x0022 | -| * MicrophoneAGCEnabled | 0x0023 | -| * ImageRotation | 0x0024 | -| * ImageFlipHorizontal | 0x0025 | -| * ImageFlipVertical | 0x0026 | -| * LocalVideoRecordingEnabled | 0x0027 | -| * LocalSnapshotRecordingEnabled | 0x0028 | -| * StatusLightEnabled | 0x0029 | -| * StatusLightBrightness | 0x002A | +| * FabricsUsingCamera | 0x000E | +| * AllocatedVideoStreams | 0x000F | +| * AllocatedAudioStreams | 0x0010 | +| * AllocatedSnapshotStreams | 0x0011 | +| * RankedVideoStreamPrioritiesList | 0x0012 | +| * SoftRecordingPrivacyModeEnabled | 0x0013 | +| * SoftLivestreamPrivacyModeEnabled | 0x0014 | +| * HardPrivacyModeOn | 0x0015 | +| * NightVision | 0x0016 | +| * NightVisionIllum | 0x0017 | +| * Viewport | 0x0018 | +| * SpeakerMuted | 0x0019 | +| * SpeakerVolumeLevel | 0x001A | +| * SpeakerMaxLevel | 0x001B | +| * SpeakerMinLevel | 0x001C | +| * MicrophoneMuted | 0x001D | +| * MicrophoneVolumeLevel | 0x001E | +| * MicrophoneMaxLevel | 0x001F | +| * MicrophoneMinLevel | 0x0020 | +| * MicrophoneAGCEnabled | 0x0021 | +| * ImageRotation | 0x0022 | +| * ImageFlipHorizontal | 0x0023 | +| * ImageFlipVertical | 0x0024 | +| * LocalVideoRecordingEnabled | 0x0025 | +| * LocalSnapshotRecordingEnabled | 0x0026 | +| * StatusLightEnabled | 0x0027 | +| * StatusLightBrightness | 0x0028 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * AttributeList | 0xFFFB | @@ -151138,7 +151136,7 @@ class CameraAvStreamManagementSnapshotStreamAllocate : public ClusterCommand { AddArgument("ImageCodec", 0, UINT8_MAX, &mRequest.imageCodec); #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL - AddArgument("FrameRate", 0, UINT16_MAX, &mRequest.frameRate); + AddArgument("MaxFrameRate", 0, UINT16_MAX, &mRequest.maxFrameRate); #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("BitRate", 0, UINT32_MAX, &mRequest.bitRate); @@ -151170,7 +151168,7 @@ class CameraAvStreamManagementSnapshotStreamAllocate : public ClusterCommand { params.imageCodec = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.imageCodec)]; #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL - params.frameRate = [NSNumber numberWithUnsignedShort:mRequest.frameRate]; + params.maxFrameRate = [NSNumber numberWithUnsignedShort:mRequest.maxFrameRate]; #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL params.bitRate = [NSNumber numberWithUnsignedInt:mRequest.bitRate]; @@ -152633,176 +152631,6 @@ class SubscribeAttributeCameraAvStreamManagementHDRModeEnabled : public Subscrib #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL -/* - * Attribute CurrentVideoCodecs - */ -class ReadCameraAvStreamManagementCurrentVideoCodecs : public ReadAttribute { -public: - ReadCameraAvStreamManagementCurrentVideoCodecs() - : ReadAttribute("current-video-codecs") - { - } - - ~ReadCameraAvStreamManagementCurrentVideoCodecs() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::CameraAvStreamManagement::Id; - constexpr chip::AttributeId attributeId = chip::app::Clusters::CameraAvStreamManagement::Attributes::CurrentVideoCodecs::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - __auto_type * cluster = [[MTRBaseClusterCameraAVStreamManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - [cluster readAttributeCurrentVideoCodecsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"CameraAVStreamManagement.CurrentVideoCodecs response %@", [value description]); - if (error == nil) { - RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); - } else { - LogNSError("CameraAVStreamManagement CurrentVideoCodecs read Error", error); - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeCameraAvStreamManagementCurrentVideoCodecs : public SubscribeAttribute { -public: - SubscribeAttributeCameraAvStreamManagementCurrentVideoCodecs() - : SubscribeAttribute("current-video-codecs") - { - } - - ~SubscribeAttributeCameraAvStreamManagementCurrentVideoCodecs() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::CameraAvStreamManagement::Id; - constexpr chip::CommandId attributeId = chip::app::Clusters::CameraAvStreamManagement::Attributes::CurrentVideoCodecs::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - __auto_type * cluster = [[MTRBaseClusterCameraAVStreamManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeCurrentVideoCodecsWithParams:params - subscriptionEstablished:^() { mSubscriptionEstablished = YES; } - reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) { - NSLog(@"CameraAVStreamManagement.CurrentVideoCodecs response %@", [value description]); - if (error == nil) { - RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); - } else { - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - -/* - * Attribute CurrentSnapshotConfig - */ -class ReadCameraAvStreamManagementCurrentSnapshotConfig : public ReadAttribute { -public: - ReadCameraAvStreamManagementCurrentSnapshotConfig() - : ReadAttribute("current-snapshot-config") - { - } - - ~ReadCameraAvStreamManagementCurrentSnapshotConfig() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::CameraAvStreamManagement::Id; - constexpr chip::AttributeId attributeId = chip::app::Clusters::CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); - - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - __auto_type * cluster = [[MTRBaseClusterCameraAVStreamManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - [cluster readAttributeCurrentSnapshotConfigWithCompletion:^(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"CameraAVStreamManagement.CurrentSnapshotConfig response %@", [value description]); - if (error == nil) { - RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); - } else { - LogNSError("CameraAVStreamManagement CurrentSnapshotConfig read Error", error); - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } -}; - -class SubscribeAttributeCameraAvStreamManagementCurrentSnapshotConfig : public SubscribeAttribute { -public: - SubscribeAttributeCameraAvStreamManagementCurrentSnapshotConfig() - : SubscribeAttribute("current-snapshot-config") - { - } - - ~SubscribeAttributeCameraAvStreamManagementCurrentSnapshotConfig() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::CameraAvStreamManagement::Id; - constexpr chip::CommandId attributeId = chip::app::Clusters::CameraAvStreamManagement::Attributes::CurrentSnapshotConfig::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - __auto_type * cluster = [[MTRBaseClusterCameraAVStreamManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; - if (mKeepSubscriptions.HasValue()) { - params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); - } - if (mFabricFiltered.HasValue()) { - params.filterByFabric = mFabricFiltered.Value(); - } - if (mAutoResubscribe.HasValue()) { - params.resubscribeAutomatically = mAutoResubscribe.Value(); - } - [cluster subscribeAttributeCurrentSnapshotConfigWithParams:params - subscriptionEstablished:^() { mSubscriptionEstablished = YES; } - reportHandler:^(MTRCameraAVStreamManagementClusterSnapshotParamsStruct * _Nullable value, NSError * _Nullable error) { - NSLog(@"CameraAVStreamManagement.CurrentSnapshotConfig response %@", [value description]); - if (error == nil) { - RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); - } else { - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - - return CHIP_NO_ERROR; - } -}; - -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - /* * Attribute FabricsUsingCamera */ @@ -153180,58 +153008,6 @@ class ReadCameraAvStreamManagementRankedVideoStreamPrioritiesList : public ReadA } }; -class WriteCameraAvStreamManagementRankedVideoStreamPrioritiesList : public WriteAttribute { -public: - WriteCameraAvStreamManagementRankedVideoStreamPrioritiesList() - : WriteAttribute("ranked-video-stream-priorities-list") - , mComplex(&mValue) - { - AddArgument("attr-name", "ranked-video-stream-priorities-list"); - AddArgument("attr-value", &mComplex); - WriteAttribute::AddArguments(); - } - - ~WriteCameraAvStreamManagementRankedVideoStreamPrioritiesList() - { - } - - CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override - { - constexpr chip::ClusterId clusterId = chip::app::Clusters::CameraAvStreamManagement::Id; - constexpr chip::AttributeId attributeId = chip::app::Clusters::CameraAvStreamManagement::Attributes::RankedVideoStreamPrioritiesList::Id; - - ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") WriteAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); - dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); - __auto_type * cluster = [[MTRBaseClusterCameraAVStreamManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; - __auto_type * params = [[MTRWriteParams alloc] init]; - params.timedWriteTimeout = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; - params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil; - NSArray * _Nonnull value; - { // Scope for our temporary variables - auto * array_0 = [NSMutableArray new]; - for (auto & entry_0 : mValue) { - NSNumber * newElement_0; - newElement_0 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0)]; - [array_0 addObject:newElement_0]; - } - value = array_0; - } - - [cluster writeAttributeRankedVideoStreamPrioritiesListWithValue:value params:params completion:^(NSError * _Nullable error) { - if (error != nil) { - LogNSError("CameraAVStreamManagement RankedVideoStreamPrioritiesList write Error", error); - RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); - } - SetCommandExitStatus(error); - }]; - return CHIP_NO_ERROR; - } - -private: - chip::app::DataModel::List mValue; - TypedComplexArgument> mComplex; -}; - class SubscribeAttributeCameraAvStreamManagementRankedVideoStreamPrioritiesList : public SubscribeAttribute { public: SubscribeAttributeCameraAvStreamManagementRankedVideoStreamPrioritiesList() @@ -181286,14 +181062,6 @@ void registerClusterCameraAvStreamManagement(Commands & commands) make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - make_unique(), // - make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL -#if MTR_ENABLE_PROVISIONAL - make_unique(), // - make_unique(), // -#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), // @@ -181312,7 +181080,6 @@ void registerClusterCameraAvStreamManagement(Commands & commands) #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // - make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL From dac4a5337cc38e1a55aecb270a6f620347e04da1 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Wed, 13 Nov 2024 18:17:33 -0800 Subject: [PATCH 003/219] [Fabric-Sync] Port commissioner control protocol implementation (#36427) * [Fabric-Sync] Port commissioner control protocol * Add device synchronization * Fix compile error * Update examples/fabric-sync/admin/DeviceSubscription.cpp Co-authored-by: Terence Hampson * Address review comments * Add debug log * Update examples/fabric-sync/admin/DeviceManager.cpp Co-authored-by: Terence Hampson * Address review comments * Add endpoint check --------- Co-authored-by: Terence Hampson --- .../device_manager/CommissionerControl.cpp | 18 + examples/fabric-sync/admin/BUILD.gn | 28 ++ .../fabric-sync/admin/BridgeSubscription.cpp | 163 +++++++++ .../fabric-sync/admin/BridgeSubscription.h | 81 +++++ .../fabric-sync/admin/CommissionerControl.cpp | 166 +++++++++ .../fabric-sync/admin/CommissionerControl.h | 129 +++++++ examples/fabric-sync/admin/DeviceManager.cpp | 336 +++++++++++++++++- examples/fabric-sync/admin/DeviceManager.h | 75 +++- .../fabric-sync/admin/DeviceSubscription.cpp | 280 +++++++++++++++ .../fabric-sync/admin/DeviceSubscription.h | 94 +++++ .../admin/DeviceSubscriptionManager.cpp | 79 ++++ .../admin/DeviceSubscriptionManager.h | 58 +++ .../admin/DeviceSynchronization.cpp | 323 +++++++++++++++++ .../fabric-sync/admin/DeviceSynchronization.h | 99 ++++++ examples/fabric-sync/admin/FabricAdmin.cpp | 117 ++++++ examples/fabric-sync/admin/FabricAdmin.h | 93 +++++ .../fabric-sync/admin/FabricSyncGetter.cpp | 125 +++++++ examples/fabric-sync/admin/FabricSyncGetter.h | 79 ++++ examples/fabric-sync/admin/PairingManager.cpp | 7 +- examples/fabric-sync/admin/PairingManager.h | 1 - examples/fabric-sync/admin/UniqueIdGetter.cpp | 145 ++++++++ examples/fabric-sync/admin/UniqueIdGetter.h | 79 ++++ examples/fabric-sync/bridge/BUILD.gn | 13 +- examples/fabric-sync/bridge/include/Bridge.h | 54 +++ .../bridge/include/BridgedDevice.h | 1 - .../bridge/include/BridgedDeviceManager.h | 1 - .../bridge/include/CHIPProjectAppConfig.h | 1 - .../include/CommissionerControlDelegate.h | 102 ++++++ .../bridge/include/FabricAdminDelegate.h | 55 +++ .../fabric-sync/bridge/include/FabricBridge.h | 161 +++++++++ examples/fabric-sync/bridge/src/Bridge.cpp | 147 ++++++++ .../fabric-sync/bridge/src/BridgedDevice.cpp | 1 - .../bridge/src/BridgedDeviceManager.cpp | 1 - .../src/CommissionerControlDelegate.cpp | 267 ++++++++++++++ .../fabric-sync/bridge/src/FabricBridge.cpp | 223 ++++++++++++ examples/fabric-sync/main.cpp | 12 +- .../fabric-sync/shell/AddBridgeCommand.cpp | 14 +- .../fabric-sync/shell/AddDeviceCommand.cpp | 3 + .../fabric-sync/shell/RemoveBridgeCommand.cpp | 4 +- .../fabric-sync/shell/RemoveDeviceCommand.cpp | 2 + examples/fabric-sync/shell/ShellCommands.cpp | 3 +- examples/fabric-sync/shell/ShellCommands.h | 1 - 42 files changed, 3624 insertions(+), 17 deletions(-) create mode 100644 examples/fabric-sync/admin/BridgeSubscription.cpp create mode 100644 examples/fabric-sync/admin/BridgeSubscription.h create mode 100644 examples/fabric-sync/admin/CommissionerControl.cpp create mode 100644 examples/fabric-sync/admin/CommissionerControl.h create mode 100644 examples/fabric-sync/admin/DeviceSubscription.cpp create mode 100644 examples/fabric-sync/admin/DeviceSubscription.h create mode 100644 examples/fabric-sync/admin/DeviceSubscriptionManager.cpp create mode 100644 examples/fabric-sync/admin/DeviceSubscriptionManager.h create mode 100644 examples/fabric-sync/admin/DeviceSynchronization.cpp create mode 100644 examples/fabric-sync/admin/DeviceSynchronization.h create mode 100644 examples/fabric-sync/admin/FabricAdmin.cpp create mode 100644 examples/fabric-sync/admin/FabricAdmin.h create mode 100644 examples/fabric-sync/admin/FabricSyncGetter.cpp create mode 100644 examples/fabric-sync/admin/FabricSyncGetter.h create mode 100644 examples/fabric-sync/admin/UniqueIdGetter.cpp create mode 100644 examples/fabric-sync/admin/UniqueIdGetter.h create mode 100644 examples/fabric-sync/bridge/include/Bridge.h create mode 100644 examples/fabric-sync/bridge/include/CommissionerControlDelegate.h create mode 100644 examples/fabric-sync/bridge/include/FabricAdminDelegate.h create mode 100644 examples/fabric-sync/bridge/include/FabricBridge.h create mode 100644 examples/fabric-sync/bridge/src/Bridge.cpp create mode 100644 examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp create mode 100644 examples/fabric-sync/bridge/src/FabricBridge.cpp diff --git a/examples/fabric-admin/device_manager/CommissionerControl.cpp b/examples/fabric-admin/device_manager/CommissionerControl.cpp index 3c6dfa5a8a..a0c24eb956 100644 --- a/examples/fabric-admin/device_manager/CommissionerControl.cpp +++ b/examples/fabric-admin/device_manager/CommissionerControl.cpp @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + #include "CommissionerControl.h" #include "DeviceManager.h" diff --git a/examples/fabric-sync/admin/BUILD.gn b/examples/fabric-sync/admin/BUILD.gn index c2ab715230..2ccc30ca2f 100644 --- a/examples/fabric-sync/admin/BUILD.gn +++ b/examples/fabric-sync/admin/BUILD.gn @@ -15,16 +15,44 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") +config("config") { + include_dirs = [ + ".", + "${chip_root}/examples/fabric-sync", + "${chip_root}/examples/platform/linux", + "${chip_root}/src/lib", + ] +} + source_set("fabric-admin-lib") { + public_configs = [ ":config" ] + sources = [ + "BridgeSubscription.cpp", + "BridgeSubscription.h", + "CommissionerControl.cpp", + "CommissionerControl.h", "DeviceManager.cpp", "DeviceManager.h", + "DeviceSubscription.cpp", + "DeviceSubscription.h", + "DeviceSubscriptionManager.cpp", + "DeviceSubscriptionManager.h", + "DeviceSynchronization.cpp", + "DeviceSynchronization.h", + "FabricAdmin.cpp", + "FabricAdmin.h", + "FabricSyncGetter.cpp", + "FabricSyncGetter.h", "PairingManager.cpp", "PairingManager.h", + "UniqueIdGetter.cpp", + "UniqueIdGetter.h", ] deps = [ "${chip_root}/examples/fabric-sync/bridge:fabric-bridge-lib", + "${chip_root}/examples/platform/linux:app-main", "${chip_root}/src/lib", ] } diff --git a/examples/fabric-sync/admin/BridgeSubscription.cpp b/examples/fabric-sync/admin/BridgeSubscription.cpp new file mode 100644 index 0000000000..e7052d7df0 --- /dev/null +++ b/examples/fabric-sync/admin/BridgeSubscription.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "BridgeSubscription.h" +#include "DeviceManager.h" + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace admin { + +namespace { + +constexpr uint16_t kSubscribeMinInterval = 0; +constexpr uint16_t kSubscribeMaxInterval = 60; + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +} // namespace + +BridgeSubscription::BridgeSubscription() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +CHIP_ERROR BridgeSubscription::StartSubscription(Controller::DeviceController & controller, NodeId nodeId, EndpointId endpointId) +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrDie(!subscriptionStarted); // Ensure it's not called multiple times. + + // Mark as started + subscriptionStarted = true; + + mEndpointId = endpointId; + + CHIP_ERROR err = controller.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to connect to remote fabric sync bridge %" CHIP_ERROR_FORMAT, err.Format()); + } + return err; +} + +void BridgeSubscription::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + if (!status.IsSuccess()) + { + ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, status.ToChipError().Format()); + return; + } + + if (data == nullptr) + { + ChipLogError(NotSpecified, "Response Failure: No Data"); + return; + } + + DeviceMgr().HandleAttributeData(path, *data); +} + +void BridgeSubscription::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status) +{ + if (status != nullptr) + { + CHIP_ERROR error = status->ToChipError(); + if (CHIP_NO_ERROR != error) + { + ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + } + + if (data == nullptr) + { + ChipLogError(NotSpecified, "Response Failure: No Data"); + return; + } + + DeviceMgr().HandleEventData(eventHeader, *data); +} + +void BridgeSubscription::OnError(CHIP_ERROR error) +{ + ChipLogProgress(NotSpecified, "Error on remote fabric sync bridge subscription: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void BridgeSubscription::OnDone(ReadClient * apReadClient) +{ + mClient.reset(); + ChipLogProgress(NotSpecified, "The remote fabric sync bridge subscription is terminated"); + + // Reset the subscription state to allow retry + subscriptionStarted = false; + + // TODO:(#36092) Fabric-Admin should attempt to re-subscribe when the subscription to the remote bridge is terminated. +} + +void BridgeSubscription::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr /* echangeMgr */, + *this /* callback */, ReadClient::InteractionType::Subscribe); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(mEndpointId, Clusters::Descriptor::Id, Clusters::Descriptor::Attributes::PartsList::Id); + + EventPathParams eventPaths[1]; + eventPaths[0] = EventPathParams(mEndpointId, Clusters::CommissionerControl::Id, + Clusters::CommissionerControl::Events::CommissioningRequestResult::Id); + eventPaths[0].mIsUrgentEvent = true; + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + readParams.mpEventPathParamsList = eventPaths; + readParams.mEventPathParamsListSize = 1; + readParams.mMinIntervalFloorSeconds = kSubscribeMinInterval; + readParams.mMaxIntervalCeilingSeconds = kSubscribeMaxInterval; + readParams.mKeepSubscriptions = true; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to issue subscription to the Descriptor Cluster of the remote bridged device."); + OnDone(nullptr); + return; + } +} + +void BridgeSubscription::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error) +{ + ChipLogError(NotSpecified, "BridgeSubscription failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + OnDone(nullptr); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/BridgeSubscription.h b/examples/fabric-sync/admin/BridgeSubscription.h new file mode 100644 index 0000000000..e5f8c73fc1 --- /dev/null +++ b/examples/fabric-sync/admin/BridgeSubscription.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include +#include + +#include +#include + +namespace admin { + +/** + * @brief Class used to subscribe to attributes and events from the remote bridged device. + * + * The Descriptor Cluster contains attributes such as the Parts List, which provides a list + * of endpoints or devices that are part of a composite device or bridge. The CommissionerControl + * Cluster generates events related to commissioning requests, which can be monitored to track + * device commissioning status. + * + * When subscribing to attributes and events of a bridged device from another fabric, the class: + * - Establishes a secure session with the device (if needed) via CASE (Chip over + * Authenticated Session Establishment) session. + * - Subscribes to the specified attributes in the Descriptor Cluster (e.g., Parts List) and + * events in the CommissionerControl Cluster (e.g., CommissioningRequestResult) of the remote + * device on the specified node and endpoint. + * - Invokes the provided callback upon successful or unsuccessful subscription, allowing + * further handling of data or errors. + * + * This class also implements the necessary callbacks to handle attribute data reports, event data, + * errors, and session establishment procedures. + */ +class BridgeSubscription : public chip::app::ReadClient::Callback +{ +public: + BridgeSubscription(); + + CHIP_ERROR StartSubscription(chip::Controller::DeviceController & controller, chip::NodeId nodeId, chip::EndpointId endpointId); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnEventData(const chip::app::EventHeader & eventHeader, chip::TLV::TLVReader * data, + const chip::app::StatusIB * status) override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + +private: + std::unique_ptr mClient; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + chip::EndpointId mEndpointId; + bool subscriptionStarted = false; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/CommissionerControl.cpp b/examples/fabric-sync/admin/CommissionerControl.cpp new file mode 100644 index 0000000000..45c7bc02da --- /dev/null +++ b/examples/fabric-sync/admin/CommissionerControl.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "CommissionerControl.h" +#include "DeviceManager.h" + +using namespace ::chip; + +namespace admin { + +void CommissionerControl::Init(Controller::DeviceCommissioner & commissioner, NodeId nodeId, EndpointId endpointId) +{ + // Ensure that mCommissioner is not already initialized + VerifyOrDie(mCommissioner == nullptr); + + ChipLogProgress(NotSpecified, "Initilize CommissionerControl"); + mCommissioner = &commissioner; + mDestinationId = nodeId; + mEndpointId = endpointId; +} + +CHIP_ERROR CommissionerControl::RequestCommissioningApproval(uint64_t requestId, uint16_t vendorId, uint16_t productId, + Optional label) +{ + VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ChipLogProgress(NotSpecified, "Sending RequestCommissioningApproval to node " ChipLogFormatX64, + ChipLogValueX64(mDestinationId)); + + mRequestCommissioningApproval.requestID = requestId; + mRequestCommissioningApproval.vendorID = static_cast(vendorId); + mRequestCommissioningApproval.productID = productId; + + if (label.HasValue()) + { + VerifyOrReturnError(label.Value().size() <= kMaxDeviceLabelLength, CHIP_ERROR_BUFFER_TOO_SMALL); + memcpy(mLabelBuffer, label.Value().data(), label.Value().size()); + mRequestCommissioningApproval.label = Optional>(CharSpan(mLabelBuffer, label.Value().size())); + } + + mCommandType = CommandType::kRequestCommissioningApproval; + return mCommissioner->GetConnectedDevice(mDestinationId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); +} + +CHIP_ERROR CommissionerControl::CommissionNode(uint64_t requestId, uint16_t responseTimeoutSeconds) +{ + VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ChipLogProgress(NotSpecified, "Sending CommissionNode to node " ChipLogFormatX64, ChipLogValueX64(mDestinationId)); + + mCommissionNode.requestID = requestId; + mCommissionNode.responseTimeoutSeconds = responseTimeoutSeconds; + + mCommandType = CommandType::kCommissionNode; + return mCommissioner->GetConnectedDevice(mDestinationId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); +} + +void CommissionerControl::OnResponse(app::CommandSender * client, const app::ConcreteCommandPath & path, + const app::StatusIB & status, TLV::TLVReader * data) +{ + ChipLogProgress(NotSpecified, "CommissionerControl: OnResponse."); + + CHIP_ERROR error = status.ToChipError(); + if (CHIP_NO_ERROR != error) + { + ChipLogError(NotSpecified, "Response Failure: %s", ErrorStr(error)); + return; + } + + if (data != nullptr) + { + DeviceMgr().HandleCommandResponse(path, *data); + } +} + +void CommissionerControl::OnError(const app::CommandSender * client, CHIP_ERROR error) +{ + // Handle the error, then reset mCommandSender + ChipLogProgress(NotSpecified, "CommissionerControl: OnError: Error: %s", ErrorStr(error)); +} + +void CommissionerControl::OnDone(app::CommandSender * client) +{ + ChipLogProgress(NotSpecified, "CommissionerControl: OnDone."); + + switch (mCommandType) + { + case CommandType::kRequestCommissioningApproval: + ChipLogProgress(NotSpecified, "CommissionerControl: Command RequestCommissioningApproval has been successfully processed."); + break; + + case CommandType::kCommissionNode: + ChipLogProgress(NotSpecified, "CommissionerControl: Command CommissionNode has been successfully processed."); + break; + + default: + ChipLogError(NotSpecified, "CommissionerControl: Unknown or unhandled command type in OnDone."); + break; + } + + // Reset command type to undefined after processing is done + mCommandType = CommandType::kUndefined; + + // Ensure that mCommandSender is cleaned up after it is done + mCommandSender.reset(); +} + +CHIP_ERROR CommissionerControl::SendCommandForType(CommandType commandType, DeviceProxy * device) +{ + ChipLogProgress(AppServer, "Sending command with Endpoint ID: %d, Command Type: %d", mEndpointId, + static_cast(commandType)); + + switch (commandType) + { + case CommandType::kRequestCommissioningApproval: + return SendCommand(device, mEndpointId, app::Clusters::CommissionerControl::Id, + app::Clusters::CommissionerControl::Commands::RequestCommissioningApproval::Id, + mRequestCommissioningApproval); + case CommandType::kCommissionNode: + return SendCommand(device, mEndpointId, app::Clusters::CommissionerControl::Id, + app::Clusters::CommissionerControl::Commands::CommissionNode::Id, mCommissionNode); + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } +} + +void CommissionerControl::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, + const SessionHandle & sessionHandle) +{ + CommissionerControl * self = reinterpret_cast(context); + VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); + + OperationalDeviceProxy device(&exchangeMgr, sessionHandle); + + CHIP_ERROR err = self->SendCommandForType(self->mCommandType, &device); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to send CommissionerControl command."); + self->OnDone(nullptr); + } +} + +void CommissionerControl::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err) +{ + LogErrorOnFailure(err); + CommissionerControl * self = reinterpret_cast(context); + VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null")); + self->OnDone(nullptr); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/CommissionerControl.h b/examples/fabric-sync/admin/CommissionerControl.h new file mode 100644 index 0000000000..392367d6c0 --- /dev/null +++ b/examples/fabric-sync/admin/CommissionerControl.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include +#include + +namespace admin { + +/** + * @class CommissionerControl + * @brief This class handles sending CHIP commands related to commissioning, including sending + * commissioning approval requests and commissioning nodes. + * + * The class acts as a command sender and implements the `chip::app::CommandSender::Callback` interface + * to handle responses, errors, and completion events for the commands it sends. It relies on external + * CCTRL delegate and server mechanisms to manage the overall protocol and state transitions, including + * processing the CommissioningRequestResult and invoking CommissionNode. + */ +class CommissionerControl : public chip::app::CommandSender::Callback +{ +public: + CommissionerControl() : + mOnDeviceConnectedCallback(OnDeviceConnectedFn, this), mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this) + {} + + /** + * @brief Initializes the CommissionerControl with a DeviceCommissioner, NodeId, and EndpointId. + * + * @param commissioner The DeviceCommissioner to use for the commissioning process. + * @param nodeId The node ID of the remote fabric bridge. + * @param endpointId The endpoint on which to send CommissionerControl commands. + */ + void Init(chip::Controller::DeviceCommissioner & commissioner, chip::NodeId nodeId, chip::EndpointId endpointId); + + /** + * @brief Sends a RequestCommissioningApproval command to the device. + * + * @param requestId The unique request ID. + * @param vendorId The vendor ID of the device. + * @param productId The product ID of the device. + * @param label Optional label for the device. + * @return CHIP_ERROR CHIP_NO_ERROR on success, or an appropriate error code on failure. + */ + CHIP_ERROR RequestCommissioningApproval(uint64_t requestId, uint16_t vendorId, uint16_t productId, + chip::Optional label); + /** + * @brief Sends a CommissionNode command to the device. + * + * @param requestId The unique request ID. + * @param responseTimeoutSeconds Timeout for the response in seconds. + * @return CHIP_ERROR CHIP_NO_ERROR on success, or an appropriate error code on failure. + */ + CHIP_ERROR CommissionNode(uint64_t requestId, uint16_t responseTimeoutSeconds); + + /////////// CommandSender Callback Interface ///////// + virtual void OnResponse(chip::app::CommandSender * client, const chip::app::ConcreteCommandPath & path, + const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override; + + virtual void OnError(const chip::app::CommandSender * client, CHIP_ERROR error) override; + + virtual void OnDone(chip::app::CommandSender * client) override; + +private: + static constexpr uint16_t kMaxDeviceLabelLength = 64; + + enum class CommandType : uint8_t + { + kUndefined = 0, + kRequestCommissioningApproval = 1, + kCommissionNode = 2, + }; + + template + CHIP_ERROR SendCommand(chip::DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, + chip::CommandId commandId, const T & value) + { + chip::app::CommandPathParams commandPath = { endpointId, clusterId, commandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + mCommandSender = std::make_unique(this, device->GetExchangeManager(), false, false, + device->GetSecureSession().Value()->AllowsLargePayload()); + + VerifyOrReturnError(mCommandSender != nullptr, CHIP_ERROR_NO_MEMORY); + + chip::app::CommandSender::AddRequestDataParameters addRequestDataParams(chip::NullOptional); + ReturnErrorOnFailure(mCommandSender->AddRequestData(commandPath, value, addRequestDataParams)); + ReturnErrorOnFailure(mCommandSender->SendCommandRequest(device->GetSecureSession().Value())); + + return CHIP_NO_ERROR; + } + + CHIP_ERROR SendCommandForType(CommandType commandType, chip::DeviceProxy * device); + + static void OnDeviceConnectedFn(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle); + static void OnDeviceConnectionFailureFn(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR error); + + // Private data members + chip::Controller::DeviceCommissioner * mCommissioner = nullptr; + std::unique_ptr mCommandSender; + chip::NodeId mDestinationId = chip::kUndefinedNodeId; + chip::EndpointId mEndpointId = chip::kRootEndpointId; + CommandType mCommandType = CommandType::kUndefined; + char mLabelBuffer[kMaxDeviceLabelLength]; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + + chip::app::Clusters::CommissionerControl::Commands::RequestCommissioningApproval::Type mRequestCommissioningApproval; + chip::app::Clusters::CommissionerControl::Commands::CommissionNode::Type mCommissionNode; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 76863e6a33..9848d2f68d 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * @@ -18,6 +17,9 @@ #include "DeviceManager.h" +#include +#include +#include #include #include @@ -27,9 +29,18 @@ using namespace chip; namespace admin { + +namespace { + +constexpr EndpointId kAggregatorEndpointId = 1; + +} // namespace + // Define the static member DeviceManager DeviceManager::sInstance; +LinuxCommissionableDataProvider sCommissionableDataProvider; + void DeviceManager::Init() { // TODO: (#34113) Init mLastUsedNodeId from chip config file @@ -60,6 +71,68 @@ void DeviceManager::UpdateLastUsedNodeId(NodeId nodeId) void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; + + if (mRemoteBridgeNodeId != kUndefinedNodeId) + { + mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); + } +} + +SyncedDevice * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) +{ + for (auto & device : mSyncedDevices) + { + if (device.GetEndpointId() == endpointId) + { + return const_cast(&device); + } + } + return nullptr; +} + +SyncedDevice * DeviceManager::FindDeviceByNode(NodeId nodeId) +{ + for (auto & device : mSyncedDevices) + { + if (device.GetNodeId() == nodeId) + { + return const_cast(&device); + } + } + return nullptr; +} + +void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, + uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) +{ + ChipLogProgress(NotSpecified, "Opening commissioning window of the local bridge"); + + auto & commissionMgr = Server::GetInstance().GetCommissioningWindowManager(); + auto commissioningTimeout = System::Clock::Seconds16(commissioningTimeoutSec); + + Optional> spake2pVerifier = verifier.empty() + ? Optional>::Missing() + : Optional>(std::vector(verifier.begin(), verifier.end())); + + Optional> spake2pSalt = salt.empty() + ? Optional>::Missing() + : Optional>(std::vector(salt.begin(), salt.end())); + + CHIP_ERROR err = + sCommissionableDataProvider.Init(spake2pVerifier, spake2pSalt, iterations, Optional(), discriminator); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to initialize the commissionable data provider of the local bridge: %s", ErrorStr(err)); + return; + } + + DeviceLayer::SetCommissionableDataProvider(&sCommissionableDataProvider); + + err = commissionMgr.OpenBasicCommissioningWindow(commissioningTimeout); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to open commissioning window of the local bridge: %s", ErrorStr(err)); + } } CHIP_ERROR DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, @@ -137,4 +210,265 @@ CHIP_ERROR DeviceManager::UnpairRemoteDevice(NodeId nodeId) return CHIP_NO_ERROR; } +void DeviceManager::SubscribeRemoteFabricBridge() +{ + ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); + + CHIP_ERROR error = mBridgeSubscriber.StartSubscription(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, + kAggregatorEndpointId); + + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to subscribe to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, + mRemoteBridgeNodeId, error.Format()); + return; + } +} + +void DeviceManager::ReadSupportedDeviceCategories() +{ + if (!IsFabricSyncReady()) + { + // print to console + fprintf(stderr, "Remote Fabric Bridge is not configured yet.\n"); + return; + } + + ChipLogProgress(NotSpecified, "Read SupportedDeviceCategories from the remote bridge."); + + CHIP_ERROR error = mFabricSyncGetter.GetFabricSynchronizationData( + [this](TLV::TLVReader & data) { this->HandleReadSupportedDeviceCategories(data); }, + PairingManager::Instance().CurrentCommissioner(), this->GetRemoteBridgeNodeId(), kAggregatorEndpointId); + + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, + mRemoteBridgeNodeId, error.Format()); + } +} + +void DeviceManager::HandleReadSupportedDeviceCategories(TLV::TLVReader & data) +{ + ChipLogProgress(NotSpecified, "Attribute SupportedDeviceCategories detected."); + + BitMask value; + CHIP_ERROR error = app::DataModel::Decode(data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode attribute value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + if (value.Has(app::Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization)) + { + ChipLogProgress(NotSpecified, "Remote Fabric-Bridge supports Fabric Synchronization, start reverse commissioning."); + RequestCommissioningApproval(); + } + else + { + ChipLogProgress(NotSpecified, "Remote Fabric-Bridge does not support Fabric Synchronization."); + } +} + +void DeviceManager::RequestCommissioningApproval() +{ + ChipLogProgress(NotSpecified, "Starting reverse commissioning for bridge device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(mRemoteBridgeNodeId)); + + uint64_t requestId = Crypto::GetRandU64(); + uint16_t vendorId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID); + uint16_t productId = static_cast(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID); + + CHIP_ERROR error = mCommissionerControl.RequestCommissioningApproval(requestId, vendorId, productId, NullOptional); + + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to request commissioning-approval to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, + mRemoteBridgeNodeId, error.Format()); + return; + } + + mRequestId = requestId; +} + +void DeviceManager::HandleCommissioningRequestResult(TLV::TLVReader & data) +{ + ChipLogProgress(NotSpecified, "CommissioningRequestResult event received."); + + app::Clusters::CommissionerControl::Events::CommissioningRequestResult::DecodableType value; + CHIP_ERROR error = app::DataModel::Decode(data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode event value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + if (value.requestID != mRequestId) + { + ChipLogError(NotSpecified, "The RequestId does not match the RequestId provided to RequestCommissioningApproval"); + return; + } + + if (value.statusCode != static_cast(Protocols::InteractionModel::Status::Success)) + { + ChipLogError(NotSpecified, "The server is not ready to begin commissioning the requested device"); + return; + } + + // The server is ready to begin commissioning the requested device, request the Commissioner Control Server to begin + // commissioning a previously approved request. + SendCommissionNodeRequest(value.requestID, kResponseTimeoutSeconds); +} + +void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) +{ + ChipLogProgress(NotSpecified, "Attribute PartsList change detected:"); + + app::DataModel::DecodableList value; + CHIP_ERROR error = app::DataModel::Decode(data, value); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode attribute value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + std::set newEndpoints; + + // Populate the newEndpoints set from the decoded value using an iterator + auto iter = value.begin(); + while (iter.Next()) + { + newEndpoints.insert(iter.GetValue()); + } + + if (iter.GetStatus() != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to iterate over decoded attribute value."); + return; + } + + // Compare newEndpoints with mSyncedDevices to determine added and removed endpoints + std::vector addedEndpoints; + std::vector removedEndpoints; + + // Note: We're using vectors and manual searches instead of set operations + // because we need to work with the SyncedDevice objects in mSyncedDevices, + // not just their EndpointIds. This approach allows us to access the full + // Device information when processing changes. + + // Find added endpoints + for (const auto & endpoint : newEndpoints) + { + if (FindDeviceByEndpoint(endpoint) == nullptr) + { + addedEndpoints.push_back(endpoint); + } + } + + // Find removed endpoints + for (auto & device : mSyncedDevices) + { + EndpointId endpointId = device.GetEndpointId(); + if (newEndpoints.find(endpointId) == newEndpoints.end()) + { + removedEndpoints.push_back(endpointId); + } + } + + // Process added endpoints + for (const auto & endpoint : addedEndpoints) + { + // print to console + fprintf(stderr, "A new device is added on Endpoint: %u\n", endpoint); + } + + // Process removed endpoints + for (const auto & endpoint : removedEndpoints) + { + ChipLogProgress(NotSpecified, "Endpoint removed: %u", endpoint); + + SyncedDevice * device = FindDeviceByEndpoint(endpoint); + + if (device == nullptr) + { + ChipLogProgress(NotSpecified, "No device on Endpoint: %u", endpoint); + continue; + } + } +} + +void DeviceManager::SendCommissionNodeRequest(uint64_t requestId, uint16_t responseTimeoutSeconds) +{ + ChipLogProgress(NotSpecified, "Request the Commissioner Control Server to begin commissioning a previously approved request."); + + CHIP_ERROR error = mCommissionerControl.CommissionNode(requestId, responseTimeoutSeconds); + + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to send CommissionNode command to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, + mRemoteBridgeNodeId, error.Format()); + return; + } +} + +void DeviceManager::HandleReverseOpenCommissioningWindow(TLV::TLVReader & data) +{ + ChipLogProgress(NotSpecified, "Handle ReverseOpenCommissioningWindow command."); + + app::Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::DecodableType value; + CHIP_ERROR error = app::DataModel::Decode(data, value); + + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to decode command response value. Error: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + + // Log all fields + ChipLogProgress(NotSpecified, "DecodableType fields:"); + ChipLogProgress(NotSpecified, " commissioningTimeout: %u", value.commissioningTimeout); + ChipLogProgress(NotSpecified, " discriminator: %u", value.discriminator); + ChipLogProgress(NotSpecified, " iterations: %u", value.iterations); + ChipLogProgress(NotSpecified, " PAKEPasscodeVerifier size: %lu", value.PAKEPasscodeVerifier.size()); + ChipLogProgress(NotSpecified, " salt size: %lu", value.salt.size()); + + OpenLocalBridgeCommissioningWindow(value.iterations, value.commissioningTimeout, value.discriminator, + ByteSpan(value.salt.data(), value.salt.size()), + ByteSpan(value.PAKEPasscodeVerifier.data(), value.PAKEPasscodeVerifier.size())); +} + +void DeviceManager::HandleAttributeData(const app::ConcreteDataAttributePath & path, TLV::TLVReader & data) +{ + if (path.mClusterId == app::Clusters::Descriptor::Id && + path.mAttributeId == app::Clusters::Descriptor::Attributes::PartsList::Id) + { + HandleAttributePartsListUpdate(data); + return; + } +} + +void DeviceManager::HandleEventData(const app::EventHeader & header, TLV::TLVReader & data) +{ + if (header.mPath.mClusterId == app::Clusters::CommissionerControl::Id && + header.mPath.mEventId == app::Clusters::CommissionerControl::Events::CommissioningRequestResult::Id) + { + HandleCommissioningRequestResult(data); + } +} + +void DeviceManager::HandleCommandResponse(const app::ConcreteCommandPath & path, TLV::TLVReader & data) +{ + ChipLogProgress(NotSpecified, "Command Response received."); + + if (path.mClusterId == app::Clusters::CommissionerControl::Id && + path.mCommandId == app::Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Id) + { + VerifyOrDie(path.mEndpointId == kAggregatorEndpointId); + HandleReverseOpenCommissioningWindow(data); + } +} + } // namespace admin diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index db6ad9b528..b92154c1e6 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * @@ -18,13 +17,38 @@ #pragma once +#include "BridgeSubscription.h" +#include "CommissionerControl.h" +#include "FabricSyncGetter.h" #include "PairingManager.h" #include #include +#include namespace admin { +constexpr uint32_t kDefaultSetupPinCode = 20202021; +constexpr uint16_t kResponseTimeoutSeconds = 30; + +class SyncedDevice +{ +public: + SyncedDevice(chip::NodeId nodeId, chip::EndpointId endpointId) : mNodeId(nodeId), mEndpointId(endpointId) {} + + chip::NodeId GetNodeId() const { return mNodeId; } + chip::EndpointId GetEndpointId() const { return mEndpointId; } + + bool operator<(const SyncedDevice & other) const + { + return mNodeId < other.mNodeId || (mNodeId == other.mNodeId && mEndpointId < other.mEndpointId); + } + +private: + chip::NodeId mNodeId; + chip::EndpointId mEndpointId; +}; + class DeviceManager { public: @@ -51,6 +75,22 @@ class DeviceManager */ bool IsCurrentBridgeDevice(chip::NodeId nodeId) const { return nodeId == mRemoteBridgeNodeId; } + /** + * @brief Open the commissioning window of the local bridge. + * + * @param iterations The number of PBKDF (Password-Based Key Derivation Function) iterations to use + * for deriving the PAKE (Password Authenticated Key Exchange) verifier. + * @param commissioningTimeoutSec The time in seconds before the commissioning window closes. This value determines + * how long the commissioning window remains open for incoming connections. + * @param discriminator The device-specific discriminator, determined during commissioning, which helps + * to uniquely identify the device among others. + * @param salt The salt used in the cryptographic operations for commissioning. + * @param verifier The PAKE verifier used to authenticate the commissioning process. + * + */ + void OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, + const chip::ByteSpan & salt, const chip::ByteSpan & verifier); + /** * @brief Pair a remote fabric bridge with a given node ID. * @@ -116,9 +156,34 @@ class DeviceManager */ CHIP_ERROR UnpairRemoteDevice(chip::NodeId nodeId); + void SubscribeRemoteFabricBridge(); + + void ReadSupportedDeviceCategories(); + + void HandleAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader & data); + + void HandleEventData(const chip::app::EventHeader & header, chip::TLV::TLVReader & data); + + void HandleCommandResponse(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader & data); + + SyncedDevice * FindDeviceByEndpoint(chip::EndpointId endpointId); + SyncedDevice * FindDeviceByNode(chip::NodeId nodeId); + private: friend DeviceManager & DeviceMgr(); + void RequestCommissioningApproval(); + + void HandleReadSupportedDeviceCategories(chip::TLV::TLVReader & data); + + void HandleCommissioningRequestResult(chip::TLV::TLVReader & data); + + void HandleAttributePartsListUpdate(chip::TLV::TLVReader & data); + + void SendCommissionNodeRequest(uint64_t requestId, uint16_t responseTimeoutSeconds); + + void HandleReverseOpenCommissioningWindow(chip::TLV::TLVReader & data); + static DeviceManager sInstance; chip::NodeId mLastUsedNodeId = 0; @@ -127,7 +192,13 @@ class DeviceManager // This represents the bridge on the other ecosystem. chip::NodeId mRemoteBridgeNodeId = chip::kUndefinedNodeId; - bool mInitialized = false; + std::set mSyncedDevices; + bool mInitialized = false; + uint64_t mRequestId = 0; + + BridgeSubscription mBridgeSubscriber; + CommissionerControl mCommissionerControl; + FabricSyncGetter mFabricSyncGetter; }; /** diff --git a/examples/fabric-sync/admin/DeviceSubscription.cpp b/examples/fabric-sync/admin/DeviceSubscription.cpp new file mode 100644 index 0000000000..9379df6910 --- /dev/null +++ b/examples/fabric-sync/admin/DeviceSubscription.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "DeviceSubscription.h" +#include "DeviceManager.h" + +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace admin { + +namespace { + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +} // namespace + +DeviceSubscription::DeviceSubscription() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +void DeviceSubscription::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + VerifyOrDie(path.mEndpointId == kRootEndpointId); + VerifyOrDie(path.mClusterId == Clusters::AdministratorCommissioning::Id); + + switch (path.mAttributeId) + { + case Clusters::AdministratorCommissioning::Attributes::WindowStatus::Id: { + Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum windowStatus; + CHIP_ERROR err = data->Get(windowStatus); + VerifyOrReturn(err == CHIP_NO_ERROR, ChipLogError(NotSpecified, "Failed to read WindowStatus")); + VerifyOrReturn(windowStatus != Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kUnknownEnumValue); + mCurrentAdministratorCommissioningAttributes.windowStatus = windowStatus; + mChangeDetected = true; + break; + } + case Clusters::AdministratorCommissioning::Attributes::AdminFabricIndex::Id: { + FabricIndex fabricIndex; + CHIP_ERROR err = data->Get(fabricIndex); + if (err == CHIP_NO_ERROR) + { + mCurrentAdministratorCommissioningAttributes.openerFabricIndex = fabricIndex; + } + else + { + mCurrentAdministratorCommissioningAttributes.openerFabricIndex.reset(); + } + + mChangeDetected = true; + break; + } + case Clusters::AdministratorCommissioning::Attributes::AdminVendorId::Id: { + VendorId vendorId; + CHIP_ERROR err = data->Get(vendorId); + if (err == CHIP_NO_ERROR) + { + mCurrentAdministratorCommissioningAttributes.openerVendorId = vendorId; + } + else + { + mCurrentAdministratorCommissioningAttributes.openerVendorId.reset(); + } + + mChangeDetected = true; + break; + } + default: + break; + } +} + +void DeviceSubscription::OnReportEnd() +{ + // Report end is at the end of all attributes (success) + if (mChangeDetected) + { + CHIP_ERROR err = + bridge::FabricBridge::Instance().AdminCommissioningAttributeChanged(mCurrentAdministratorCommissioningAttributes); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Cannot forward Administrator Commissioning Attribute to fabric bridge %" CHIP_ERROR_FORMAT, + err.Format()); + } + mChangeDetected = false; + } +} + +void DeviceSubscription::OnDone(ReadClient * apReadClient) +{ + // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with + // DeviceSubscription. + MoveToState(State::AwaitingDestruction); + mOnDoneCallback(mScopedNodeId); +} + +void DeviceSubscription::OnError(CHIP_ERROR error) +{ + if (error == CHIP_ERROR_TIMEOUT && mState == State::SubscriptionStarted) + { + if (bridge::FabricBridge::Instance().DeviceReachableChanged(mCurrentAdministratorCommissioningAttributes.id, false) != + CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to update the device reachability state"); + } + } + + ChipLogProgress(NotSpecified, "Error subscribing: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void DeviceSubscription::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + if (mState == State::Stopping) + { + // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with + // DeviceSubscription. + MoveToState(State::AwaitingDestruction); + mOnDoneCallback(mScopedNodeId); + return; + } + VerifyOrDie(mState == State::Connecting); + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr /* echangeMgr */, + *this /* callback */, ReadClient::InteractionType::Subscribe); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(kRootEndpointId, Clusters::AdministratorCommissioning::Id); + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + readParams.mMaxIntervalCeilingSeconds = 5 * 60; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to issue subscription to AdministratorCommissioning data"); + // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with + // DeviceSubscription. + MoveToState(State::AwaitingDestruction); + mOnDoneCallback(mScopedNodeId); + return; + } + MoveToState(State::SubscriptionStarted); +} + +void DeviceSubscription::MoveToState(const State aTargetState) +{ + mState = aTargetState; + ChipLogDetail(NotSpecified, "DeviceSubscription moving to [%10.10s]", GetStateStr()); +} + +const char * DeviceSubscription::GetStateStr() const +{ + switch (mState) + { + case State::Idle: + return "Idle"; + + case State::Connecting: + return "Connecting"; + + case State::Stopping: + return "Stopping"; + + case State::SubscriptionStarted: + return "SubscriptionStarted"; + + case State::AwaitingDestruction: + return "AwaitingDestruction"; + } + return "N/A"; +} + +void DeviceSubscription::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error) +{ + VerifyOrDie(mState == State::Connecting || mState == State::Stopping); + ChipLogError(NotSpecified, "DeviceSubscription failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + + if (mState == State::Connecting) + { + if (bridge::FabricBridge::Instance().DeviceReachableChanged(mCurrentAdministratorCommissioningAttributes.id, false) != + CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to update the device reachability state"); + } + } + + // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with + // DeviceSubscription. + MoveToState(State::AwaitingDestruction); + mOnDoneCallback(mScopedNodeId); +} + +CHIP_ERROR DeviceSubscription::StartSubscription(OnDoneCallback onDoneCallback, Controller::DeviceController & controller, + ScopedNodeId scopedNodeId) +{ + assertChipStackLockedByCurrentThread(); + VerifyOrDie(mState == State::Idle); + VerifyOrReturnError(controller.GetFabricIndex() == scopedNodeId.GetFabricIndex(), CHIP_ERROR_INVALID_ARGUMENT); + + mScopedNodeId = scopedNodeId; + + mCurrentAdministratorCommissioningAttributes = AdministratorCommissioningChanged_init_default; + mCurrentAdministratorCommissioningAttributes.id = scopedNodeId; + mCurrentAdministratorCommissioningAttributes.windowStatus = + Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen; + + mOnDoneCallback = onDoneCallback; + MoveToState(State::Connecting); + CHIP_ERROR err = + controller.GetConnectedDevice(scopedNodeId.GetNodeId(), &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + MoveToState(State::Idle); + } + return err; +} + +void DeviceSubscription::StopSubscription() +{ + assertChipStackLockedByCurrentThread(); + VerifyOrDie(mState != State::Idle); + // Something is seriously wrong if we die on the line below + VerifyOrDie(mState != State::AwaitingDestruction); + + if (mState == State::Stopping) + { + // Stop is called again while we are still waiting on connected callbacks + return; + } + + if (mState == State::Connecting) + { + MoveToState(State::Stopping); + return; + } + + // By calling reset on our ReadClient we terminate the subscription. + VerifyOrDie(mClient); + mClient.reset(); + // After calling mOnDoneCallback we are indicating that `this` is deleted and we shouldn't do anything else with + // DeviceSubscription. + MoveToState(State::AwaitingDestruction); + mOnDoneCallback(mScopedNodeId); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSubscription.h b/examples/fabric-sync/admin/DeviceSubscription.h new file mode 100644 index 0000000000..59169223e6 --- /dev/null +++ b/examples/fabric-sync/admin/DeviceSubscription.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ +#pragma once + +#include +#include +#include +#include +#include + +namespace admin { + +class DeviceSubscriptionManager; + +/// Attribute subscription to attributes that are important to keep track and send to fabric-bridge +/// via RPC when change has been identified. +/// +/// An instance of DeviceSubscription is intended to be used only once. Once a DeviceSubscription is +/// terminated, either from an error or from subscriptions getting shut down, we expect the instance +/// to be deleted. Any new subscription should instantiate another instance of DeviceSubscription. +class DeviceSubscription : public chip::app::ReadClient::Callback +{ +public: + using OnDoneCallback = std::function; + + DeviceSubscription(); + + CHIP_ERROR StartSubscription(OnDoneCallback onDoneCallback, chip::Controller::DeviceController & controller, + chip::ScopedNodeId nodeId); + + /// This will trigger stopping the subscription. Once subscription is stopped the OnDoneCallback + /// provided in StartSubscription will be called to indicate that subscription have been terminated. + /// + /// Must only be called after StartSubscription was successfully called. + void StopSubscription(); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnReportEnd() override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + +private: + enum class State : uint8_t + { + Idle, ///< Default state that the object starts out in, where no work has commenced + Connecting, ///< We are waiting for OnDeviceConnected or OnDeviceConnectionFailure callbacks to be called + Stopping, ///< We are waiting for OnDeviceConnected or OnDeviceConnectionFailure callbacks so we can terminate + SubscriptionStarted, ///< We have started a subscription. + AwaitingDestruction, ///< The object has completed its work and is awaiting destruction. + }; + + void MoveToState(const State aTargetState); + const char * GetStateStr() const; + + chip::ScopedNodeId mScopedNodeId; + + OnDoneCallback mOnDoneCallback; + std::unique_ptr mClient; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + + bridge::AdministratorCommissioningChanged mCurrentAdministratorCommissioningAttributes; + + bool mChangeDetected = false; + State mState = State::Idle; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSubscriptionManager.cpp b/examples/fabric-sync/admin/DeviceSubscriptionManager.cpp new file mode 100644 index 0000000000..d2209bdd5d --- /dev/null +++ b/examples/fabric-sync/admin/DeviceSubscriptionManager.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "DeviceSubscriptionManager.h" +#include "DeviceManager.h" + +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::app; + +namespace admin { + +DeviceSubscriptionManager & DeviceSubscriptionManager::Instance() +{ + static DeviceSubscriptionManager instance; + return instance; +} + +CHIP_ERROR DeviceSubscriptionManager::StartSubscription(Controller::DeviceController & controller, ScopedNodeId scopedNodeId) +{ + assertChipStackLockedByCurrentThread(); + auto it = mDeviceSubscriptionMap.find(scopedNodeId); + VerifyOrReturnError((it == mDeviceSubscriptionMap.end()), CHIP_ERROR_INCORRECT_STATE); + + auto deviceSubscription = std::make_unique(); + VerifyOrReturnError(deviceSubscription, CHIP_ERROR_NO_MEMORY); + ReturnErrorOnFailure(deviceSubscription->StartSubscription( + [this](ScopedNodeId aNodeId) { this->DeviceSubscriptionTerminated(aNodeId); }, controller, scopedNodeId)); + + mDeviceSubscriptionMap[scopedNodeId] = std::move(deviceSubscription); + return CHIP_NO_ERROR; +} + +CHIP_ERROR DeviceSubscriptionManager::RemoveSubscription(ScopedNodeId scopedNodeId) +{ + assertChipStackLockedByCurrentThread(); + auto it = mDeviceSubscriptionMap.find(scopedNodeId); + VerifyOrReturnError((it != mDeviceSubscriptionMap.end()), CHIP_ERROR_NOT_FOUND); + // We cannot safely erase the DeviceSubscription from mDeviceSubscriptionMap. + // After calling StopSubscription we expect DeviceSubscription to eventually + // call the OnDoneCallback we provided in StartSubscription which will call + // DeviceSubscriptionTerminated where it will be erased from the + // mDeviceSubscriptionMap. + it->second->StopSubscription(); + return CHIP_NO_ERROR; +} + +void DeviceSubscriptionManager::DeviceSubscriptionTerminated(ScopedNodeId scopedNodeId) +{ + assertChipStackLockedByCurrentThread(); + auto it = mDeviceSubscriptionMap.find(scopedNodeId); + // DeviceSubscriptionTerminated is a private method that is expected to only + // be called by DeviceSubscription when it is terminal and is ready to be + // cleaned up and removed. If it is not mapped that means something has gone + // really wrong and there is likely a memory leak somewhere. + VerifyOrDie(it != mDeviceSubscriptionMap.end()); + mDeviceSubscriptionMap.erase(scopedNodeId); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSubscriptionManager.h b/examples/fabric-sync/admin/DeviceSubscriptionManager.h new file mode 100644 index 0000000000..eb32d3f439 --- /dev/null +++ b/examples/fabric-sync/admin/DeviceSubscriptionManager.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ +#pragma once + +#include "DeviceSubscription.h" + +#include +#include +#include + +#include + +namespace admin { + +class DeviceSubscriptionManager +{ +public: + static DeviceSubscriptionManager & Instance(); + + /// Usually called after we have added a synchronized device to fabric-bridge to monitor + /// for any changes that need to be propagated to fabric-bridge. + CHIP_ERROR StartSubscription(chip::Controller::DeviceController & controller, chip::ScopedNodeId scopedNodeId); + + CHIP_ERROR RemoveSubscription(chip::ScopedNodeId scopedNodeId); + +private: + struct ScopedNodeIdHasher + { + std::size_t operator()(const chip::ScopedNodeId & scopedNodeId) const + { + std::size_t h1 = std::hash{}(scopedNodeId.GetFabricIndex()); + std::size_t h2 = std::hash{}(scopedNodeId.GetNodeId()); + // Bitshifting h2 reduces collisions when fabricIndex == nodeId. + return h1 ^ (h2 << 1); + } + }; + + void DeviceSubscriptionTerminated(chip::ScopedNodeId scopedNodeId); + + std::unordered_map, ScopedNodeIdHasher> mDeviceSubscriptionMap; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSynchronization.cpp b/examples/fabric-sync/admin/DeviceSynchronization.cpp new file mode 100644 index 0000000000..2f36eb9cb0 --- /dev/null +++ b/examples/fabric-sync/admin/DeviceSynchronization.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "DeviceSynchronization.h" +#include "DeviceManager.h" +#include "DeviceSubscriptionManager.h" + +#include +#include +#include +#include + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace admin { + +namespace { + +constexpr uint16_t kBasicInformationAttributeBufSize = 128; + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +bool SuccessOrLog(CHIP_ERROR err, const char * name) +{ + if (err == CHIP_NO_ERROR) + { + return true; + } + + ChipLogError(NotSpecified, "Failed to read %s: %" CHIP_ERROR_FORMAT, name, err.Format()); + + return false; +} + +} // namespace + +DeviceSynchronizer & DeviceSynchronizer::Instance() +{ + static DeviceSynchronizer instance; + return instance; +} + +DeviceSynchronizer::DeviceSynchronizer() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +void DeviceSynchronizer::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + VerifyOrDie(path.mEndpointId == kRootEndpointId); + VerifyOrDie(path.mClusterId == Clusters::BasicInformation::Id); + + if (!status.IsSuccess()) + { + ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, status.ToChipError().Format()); + return; + } + + switch (path.mAttributeId) + { + case Clusters::BasicInformation::Attributes::UniqueID::Id: { + char uniqueIdBuffer[kBasicInformationAttributeBufSize]; + if (SuccessOrLog(data->GetString(uniqueIdBuffer, sizeof(uniqueIdBuffer)), "UniqueId")) + { + mCurrentDeviceData.uniqueId = std::string(uniqueIdBuffer); + } + } + break; + case Clusters::BasicInformation::Attributes::VendorName::Id: { + char vendorNameBuffer[kBasicInformationAttributeBufSize]; + if (SuccessOrLog(data->GetString(vendorNameBuffer, sizeof(vendorNameBuffer)), "VendorName")) + { + mCurrentDeviceData.vendorName = std::string(vendorNameBuffer); + } + } + break; + case Clusters::BasicInformation::Attributes::ProductName::Id: { + char productNameBuffer[kBasicInformationAttributeBufSize]; + if (SuccessOrLog(data->GetString(productNameBuffer, sizeof(productNameBuffer)), "ProductName")) + { + mCurrentDeviceData.productName = std::string(productNameBuffer); + } + } + break; + case Clusters::BasicInformation::Attributes::NodeLabel::Id: { + char nodeLabelBuffer[kBasicInformationAttributeBufSize]; + if (SuccessOrLog(data->GetString(nodeLabelBuffer, sizeof(nodeLabelBuffer)), "NodeLabel")) + { + mCurrentDeviceData.nodeLabel = std::string(nodeLabelBuffer); + } + } + break; + case Clusters::BasicInformation::Attributes::HardwareVersionString::Id: { + char hardwareVersionStringBuffer[kBasicInformationAttributeBufSize]; + if (SuccessOrLog(data->GetString(hardwareVersionStringBuffer, sizeof(hardwareVersionStringBuffer)), + "HardwareVersionString")) + { + mCurrentDeviceData.hardwareVersionString = std::string(hardwareVersionStringBuffer); + } + } + break; + case Clusters::BasicInformation::Attributes::SoftwareVersionString::Id: { + char softwareVersionStringBuffer[kBasicInformationAttributeBufSize]; + if (SuccessOrLog(data->GetString(softwareVersionStringBuffer, sizeof(softwareVersionStringBuffer)), + "SoftwareVersionString")) + { + mCurrentDeviceData.softwareVersionString = std::string(softwareVersionStringBuffer); + } + } + break; + default: + break; + } +} + +void DeviceSynchronizer::OnReportEnd() +{ + // Report end is at the end of all attributes (success) + MoveToState(State::ReceivedResponse); +} + +void DeviceSynchronizer::OnDone(app::ReadClient * apReadClient) +{ + ChipLogProgress(NotSpecified, "Synchronization complete for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + + if (mState == State::ReceivedResponse && !DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + { + GetUniqueId(); + if (mState == State::GettingUid) + { + ChipLogProgress(NotSpecified, + "GetUniqueId was successful and we rely on callback to call SynchronizationCompleteAddDevice."); + return; + } + SynchronizationCompleteAddDevice(); + } + + MoveToState(State::Idle); +} + +void DeviceSynchronizer::OnError(CHIP_ERROR error) +{ + MoveToState(State::ReceivedError); + ChipLogProgress(NotSpecified, "Error fetching device data: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void DeviceSynchronizer::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr /* echangeMgr */, + *this /* callback */, ReadClient::InteractionType::Read); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(kRootEndpointId, Clusters::BasicInformation::Id); + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to issue read for BasicInformation data"); + MoveToState(State::Idle); + } + MoveToState(State::AwaitingResponse); +} + +void DeviceSynchronizer::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error) +{ + ChipLogError(NotSpecified, "Device Sync failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + MoveToState(State::Idle); +} + +void DeviceSynchronizer::StartDeviceSynchronization(Controller::DeviceController * controller, NodeId nodeId, bool deviceIsIcd) +{ + VerifyOrDie(controller); + if (mState != State::Idle) + { + ChipLogError(NotSpecified, "Device Sync NOT POSSIBLE: another sync is in progress"); + return; + } + + mNodeId = nodeId; + + ChipLogProgress(NotSpecified, "Start device synchronization for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + + mCurrentDeviceData = SynchronizedDevice_init_default; + mCurrentDeviceData.id = chip::ScopedNodeId(nodeId, controller->GetFabricIndex()); + mCurrentDeviceData.isIcd = deviceIsIcd; + + ReturnOnFailure(controller->GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback)); + mController = controller; + MoveToState(State::Connecting); +} + +void DeviceSynchronizer::GetUniqueId() +{ + VerifyOrDie(mState == State::ReceivedResponse); + VerifyOrDie(mController); + + // If we have a UniqueId we can return leaving state in ReceivedResponse. + VerifyOrReturn(!mCurrentDeviceData.uniqueId.has_value(), ChipLogDetail(NotSpecified, "We already have UniqueId")); + + auto * device = DeviceMgr().FindDeviceByNode(mNodeId); + // If there is no associated remote Fabric Sync Aggregator there is no other place for us to try + // getting the UniqueId from and can return leaving the state in ReceivedResponse. + VerifyOrReturn(device, ChipLogDetail(NotSpecified, "No remote Fabric Sync Aggregator to get UniqueId from")); + + // Because device is not-null we expect IsFabricSyncReady to be true. IsFabricSyncReady indicates we have a + // connection to the remote Fabric Sync Aggregator. + VerifyOrDie(DeviceMgr().IsFabricSyncReady()); + auto remoteBridgeNodeId = DeviceMgr().GetRemoteBridgeNodeId(); + EndpointId remoteEndpointIdOfInterest = device->GetEndpointId(); + + ChipLogDetail(NotSpecified, "Attempting to get UniqueId from remote Fabric Sync Aggregator"); + CHIP_ERROR err = mUniqueIdGetter.GetUniqueId( + [this](std::optional aUniqueId) { + if (aUniqueId.has_value()) + { + // Convert CharSpan to std::string and set it as uniqueId + this->mCurrentDeviceData.uniqueId = std::string(aUniqueId.value().data(), aUniqueId.value().size()); + } + else + { + ChipLogError(NotSpecified, "We expected to get UniqueId from remote Fabric Sync Aggregator, but failed"); + } + this->SynchronizationCompleteAddDevice(); + }, + *mController, remoteBridgeNodeId, remoteEndpointIdOfInterest); + + if (err == CHIP_NO_ERROR) + { + MoveToState(State::GettingUid); + } + else + { + ChipLogDetail(NotSpecified, "Failed to get UniqueId from remote Fabric Sync Aggregator") + } +} + +void DeviceSynchronizer::SynchronizationCompleteAddDevice() +{ + VerifyOrDie(mState == State::ReceivedResponse || mState == State::GettingUid); + ChipLogProgress(NotSpecified, "Synchronization complete and add device"); + + bridge::FabricBridge::Instance().AddSynchronizedDevice(mCurrentDeviceData); + + // TODO(#35077) Figure out how we should reflect CADMIN values of ICD. + if (!mCurrentDeviceData.isIcd) + { + VerifyOrDie(mController); + ScopedNodeId scopedNodeId(mNodeId, mController->GetFabricIndex()); + CHIP_ERROR err = DeviceSubscriptionManager::Instance().StartSubscription(*mController, scopedNodeId); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed start subscription to NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + bridge::FabricBridge::Instance().DeviceReachableChanged(mCurrentDeviceData.id, false); + } + } + + MoveToState(State::Idle); +} + +void DeviceSynchronizer::MoveToState(const State targetState) +{ + mState = targetState; + ChipLogDetail(NotSpecified, "DeviceSynchronizer moving to [%10.10s]", GetStateStr()); +} + +const char * DeviceSynchronizer::GetStateStr() const +{ + switch (mState) + { + case State::Idle: + return "Idle"; + + case State::Connecting: + return "Connecting"; + + case State::AwaitingResponse: + return "AwaitingResponse"; + + case State::ReceivedResponse: + return "ReceivedResponse"; + + case State::ReceivedError: + return "ReceivedError"; + + case State::GettingUid: + return "GettingUid"; + } + return "N/A"; +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSynchronization.h b/examples/fabric-sync/admin/DeviceSynchronization.h new file mode 100644 index 0000000000..1a72a44799 --- /dev/null +++ b/examples/fabric-sync/admin/DeviceSynchronization.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ +#pragma once + +#include "UniqueIdGetter.h" + +#include +#include +#include +#include +#include + +namespace admin { + +/// Ensures that device data is synchronized to the remote fabric bridge. +/// +/// Includes a state machine that: +/// - initiates a "read basic information data" command to fetch basic information +/// - upon receiving such information, ensures that synchronized device data is sent +/// to the remote end. +class DeviceSynchronizer : public chip::app::ReadClient::Callback +{ +public: + DeviceSynchronizer(); + + /// Usually called after commissioning is complete, initiates a + /// read of required data from the remote node ID and then will synchronize + /// the device towards the fabric bridge + /// + /// @param controller Must be a non-null pointer. The DeviceController instance + /// pointed to must out live the entire device synchronization process. + /// @param nodeId Node ID of the device we need to syncronize data from. + /// @param deviceIsIcd If the device is an ICD device. + void StartDeviceSynchronization(chip::Controller::DeviceController * controller, chip::NodeId nodeId, bool deviceIsIcd); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnReportEnd() override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + + static DeviceSynchronizer & Instance(); + +private: + enum class State : uint8_t + { + Idle, ///< Default state that the object starts out in, where no work has commenced + Connecting, ///< We are waiting for OnDeviceConnected or OnDeviceConnectionFailure callbacks to be called + AwaitingResponse, ///< We have started reading BasicInformation cluster attributes + ReceivedResponse, ///< We have received a ReportEnd from reading BasicInformation cluster attributes + ReceivedError, ///< We recieved an error while reading of BasicInformation cluster attributes + GettingUid, ///< We are getting UniqueId from the remote fabric sync bridge. + }; + + void GetUniqueId(); + void SynchronizationCompleteAddDevice(); + + void MoveToState(const State targetState); + const char * GetStateStr() const; + + std::unique_ptr mClient; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + + State mState = State::Idle; + // mController is expected to remain valid throughout the entire device synchronization process (i.e. when + // mState != Idle). + chip::Controller::DeviceController * mController = nullptr; + chip::NodeId mNodeId = chip::kUndefinedNodeId; + bridge::SynchronizedDevice mCurrentDeviceData; + UniqueIdGetter mUniqueIdGetter; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp new file mode 100644 index 0000000000..a012ac9d8c --- /dev/null +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "FabricAdmin.h" + +using namespace ::chip; + +namespace admin { + +namespace { + +constexpr uint32_t kCommissionPrepareTimeMs = 500; + +} // namespace + +FabricAdmin FabricAdmin::sInstance; + +FabricAdmin & FabricAdmin::Instance() +{ + if (!sInstance.mInitialized) + { + sInstance.Init(); + } + return sInstance; +} + +CHIP_ERROR +FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParams params, VendorId vendorId, uint16_t productId) +{ + char saltHex[Crypto::kSpake2p_Max_PBKDF_Salt_Length * 2 + 1]; + Encoding::BytesToHex(params.GetSalt().data(), params.GetSalt().size(), saltHex, sizeof(saltHex), + Encoding::HexFlags::kNullTerminate); + + ChipLogProgress(NotSpecified, "Received CommissionNode request"); + + SetupPayload setupPayload = SetupPayload(); + + setupPayload.setUpPINCode = params.GetSetupPIN(); + setupPayload.version = 0; + setupPayload.vendorID = vendorId; + setupPayload.productID = productId; + setupPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork); + + SetupDiscriminator discriminator{}; + discriminator.SetLongValue(params.GetDiscriminator()); + setupPayload.discriminator = discriminator; + + QRCodeSetupPayloadGenerator generator(setupPayload); + std::string code; + CHIP_ERROR err = generator.payloadBase38RepresentationWithAutoTLVBuffer(code); + + if (err == CHIP_NO_ERROR) + { + NodeId nodeId = DeviceMgr().GetNextAvailableNodeId(); + + // After responding with RequestCommissioningApproval to the node where the client initiated the + // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. + usleep(kCommissionPrepareTimeMs * 1000); + + DeviceMgr().PairRemoteDevice(nodeId, code.c_str()); + } + else + { + ChipLogError(NotSpecified, "Unable to generate pairing code for setup payload: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FabricAdmin::KeepActive(ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) +{ + ChipLogProgress(NotSpecified, "Received KeepActive request: Id[%d, 0x" ChipLogFormatX64 "], %u", scopedNodeId.GetFabricIndex(), + ChipLogValueX64(scopedNodeId.GetNodeId()), stayActiveDurationMs); + + KeepActiveWorkData * data = Platform::New(this, scopedNodeId, stayActiveDurationMs, timeoutMs); + VerifyOrReturnError(data != nullptr, CHIP_ERROR_NO_MEMORY); + + DeviceLayer::PlatformMgr().ScheduleWork(KeepActiveWork, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +void FabricAdmin::ScheduleSendingKeepActiveOnCheckIn(ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) +{ + // Accessing mPendingCheckIn should only be done while holding ChipStackLock + assertChipStackLockedByCurrentThread(); + + auto timeNow = System::SystemClock().GetMonotonicTimestamp(); + System::Clock::Timestamp expiryTimestamp = timeNow + System::Clock::Milliseconds64(timeoutMs); + KeepActiveDataForCheckIn checkInData = { .mStayActiveDurationMs = stayActiveDurationMs, + .mRequestExpiryTimestamp = expiryTimestamp }; + + auto it = mPendingCheckIn.find(scopedNodeId); + if (it != mPendingCheckIn.end()) + { + checkInData.mStayActiveDurationMs = std::max(checkInData.mStayActiveDurationMs, it->second.mStayActiveDurationMs); + checkInData.mRequestExpiryTimestamp = std::max(checkInData.mRequestExpiryTimestamp, it->second.mRequestExpiryTimestamp); + } + + mPendingCheckIn[scopedNodeId] = checkInData; +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h new file mode 100644 index 0000000000..1219e594fa --- /dev/null +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#pragma once + +#include "DeviceManager.h" + +#include +#include +#include +#include + +namespace admin { + +struct ScopedNodeIdHasher +{ + std::size_t operator()(const chip::ScopedNodeId & scopedNodeId) const + { + std::size_t h1 = std::hash{}(scopedNodeId.GetFabricIndex()); + std::size_t h2 = std::hash{}(scopedNodeId.GetNodeId()); + // Bitshifting h2 reduces collisions when fabricIndex == nodeId. + return h1 ^ (h2 << 1); + } +}; + +class FabricAdmin final : public bridge::FabricAdminDelegate +{ +public: + static FabricAdmin & Instance(); + + CHIP_ERROR + CommissionRemoteBridge(chip::Controller::CommissioningWindowPasscodeParams params, chip::VendorId vendorId, + uint16_t productId) override; + + CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) override; + + void ScheduleSendingKeepActiveOnCheckIn(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs); + +private: + struct KeepActiveDataForCheckIn + { + uint32_t mStayActiveDurationMs = 0; + chip::System::Clock::Timestamp mRequestExpiryTimestamp; + }; + + struct KeepActiveWorkData + { + KeepActiveWorkData(FabricAdmin * fabricAdmin, chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, + uint32_t timeoutMs) : + mFabricAdmin(fabricAdmin), + mScopedNodeId(scopedNodeId), mStayActiveDurationMs(stayActiveDurationMs), mTimeoutMs(timeoutMs) + {} + + FabricAdmin * mFabricAdmin; + chip::ScopedNodeId mScopedNodeId; + uint32_t mStayActiveDurationMs; + uint32_t mTimeoutMs; + }; + + static void KeepActiveWork(intptr_t arg) + { + KeepActiveWorkData * data = reinterpret_cast(arg); + data->mFabricAdmin->ScheduleSendingKeepActiveOnCheckIn(data->mScopedNodeId, data->mStayActiveDurationMs, data->mTimeoutMs); + chip::Platform::Delete(data); + } + + // Modifications to mPendingCheckIn should be done on the MatterEventLoop thread + // otherwise we would need a mutex protecting this data to prevent race as this + // data is accessible by both RPC thread and Matter eventloop. + std::unordered_map mPendingCheckIn; + + static FabricAdmin sInstance; + + bool mInitialized = false; + + void Init() { mInitialized = true; } +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/FabricSyncGetter.cpp b/examples/fabric-sync/admin/FabricSyncGetter.cpp new file mode 100644 index 0000000000..7e51180907 --- /dev/null +++ b/examples/fabric-sync/admin/FabricSyncGetter.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "FabricSyncGetter.h" + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace admin { + +namespace { + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +} // namespace + +FabricSyncGetter::FabricSyncGetter() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +CHIP_ERROR FabricSyncGetter::GetFabricSynchronizationData(OnDoneCallback onDoneCallback, Controller::DeviceController & controller, + NodeId nodeId, EndpointId endpointId) +{ + assertChipStackLockedByCurrentThread(); + + mEndpointId = endpointId; + mOnDoneCallback = onDoneCallback; + + CHIP_ERROR err = controller.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to connect to remote fabric bridge %" CHIP_ERROR_FORMAT, err.Format()); + } + return err; +} + +void FabricSyncGetter::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + VerifyOrDie(path.mClusterId == Clusters::CommissionerControl::Id); + + if (!status.IsSuccess()) + { + ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, status.ToChipError().Format()); + return; + } + + switch (path.mAttributeId) + { + case Clusters::CommissionerControl::Attributes::SupportedDeviceCategories::Id: { + mOnDoneCallback(*data); + break; + } + default: + break; + } +} + +void FabricSyncGetter::OnError(CHIP_ERROR error) +{ + ChipLogProgress(NotSpecified, "Error Getting SupportedDeviceCategories: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void FabricSyncGetter::OnDone(ReadClient * apReadClient) +{ + ChipLogProgress(NotSpecified, "Reading SupportedDeviceCategories is done."); +} + +void FabricSyncGetter::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr, *this /* callback */, + ReadClient::InteractionType::Read); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(mEndpointId, Clusters::CommissionerControl::Id, + Clusters::CommissionerControl::Attributes::SupportedDeviceCategories::Id); + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to read SupportedDeviceCategories from the bridged device."); + OnDone(nullptr); + return; + } +} + +void FabricSyncGetter::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error) +{ + ChipLogError(NotSpecified, "FabricSyncGetter failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + + OnDone(nullptr); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/FabricSyncGetter.h b/examples/fabric-sync/admin/FabricSyncGetter.h new file mode 100644 index 0000000000..bed3c2fbb5 --- /dev/null +++ b/examples/fabric-sync/admin/FabricSyncGetter.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include +#include + +#include +#include + +namespace admin { + +/** + * @brief Class used to get FabricSynchronization from SupportedDeviceCategories attribute of Commissioner Control Cluster. + * + * Functionality: + * - Establishes a CASE session to communicate with the remote bridge. + * - Retrieves the attribute data from the endpoint which host Aggregator. + * - Provides callbacks for success, error, and completion when retrieving data. + */ +class FabricSyncGetter : public chip::app::ReadClient::Callback +{ +public: + using OnDoneCallback = std::function; + + FabricSyncGetter(); + + /** + * @brief Initiates the process of retrieving fabric synchronization data from the target device. + * + * @param onDoneCallback A callback function to be invoked when the data retrieval is complete. + * @param controller The device controller used to establish a session with the target device. + * @param nodeId The Node ID of the target device. + * @param endpointId The Endpoint ID from which to retrieve the fabric synchronization data. + * @return CHIP_ERROR Returns an error if the process fails, CHIP_NO_ERROR on success. + */ + CHIP_ERROR GetFabricSynchronizationData(OnDoneCallback onDoneCallback, chip::Controller::DeviceController & controller, + chip::NodeId nodeId, chip::EndpointId endpointId); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + +private: + std::unique_ptr mClient; + + OnDoneCallback mOnDoneCallback; + chip::EndpointId mEndpointId; + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index a3f4af43da..ba360051a2 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * @@ -17,6 +16,8 @@ */ #include "PairingManager.h" +#include "DeviceManager.h" +#include "DeviceSynchronization.h" #include #include @@ -284,6 +285,10 @@ void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { // print to console fprintf(stderr, "New device with Node ID: " ChipLogFormatX64 " has been successfully added.\n", ChipLogValueX64(nodeId)); + + // mCommissioner has a lifetime that is the entire life of the application itself + // so it is safe to provide to StartDeviceSynchronization. + DeviceSynchronizer::Instance().StartDeviceSynchronization(mCommissioner, nodeId, false); } else { diff --git a/examples/fabric-sync/admin/PairingManager.h b/examples/fabric-sync/admin/PairingManager.h index b9b404ee76..9d109911e1 100644 --- a/examples/fabric-sync/admin/PairingManager.h +++ b/examples/fabric-sync/admin/PairingManager.h @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * diff --git a/examples/fabric-sync/admin/UniqueIdGetter.cpp b/examples/fabric-sync/admin/UniqueIdGetter.cpp new file mode 100644 index 0000000000..cc3567deda --- /dev/null +++ b/examples/fabric-sync/admin/UniqueIdGetter.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "UniqueIdGetter.h" + +using namespace ::chip; +using namespace ::chip::app; +using chip::app::ReadClient; + +namespace admin { + +namespace { + +void OnDeviceConnectedWrapper(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + reinterpret_cast(context)->OnDeviceConnected(exchangeMgr, sessionHandle); +} + +void OnDeviceConnectionFailureWrapper(void * context, const ScopedNodeId & peerId, CHIP_ERROR error) +{ + reinterpret_cast(context)->OnDeviceConnectionFailure(peerId, error); +} + +bool SuccessOrLog(CHIP_ERROR err, const char * name) +{ + if (err == CHIP_NO_ERROR) + { + return true; + } + + ChipLogError(NotSpecified, "Failed to read %s: %" CHIP_ERROR_FORMAT, name, err.Format()); + + return false; +} + +} // namespace + +UniqueIdGetter::UniqueIdGetter() : + mOnDeviceConnectedCallback(OnDeviceConnectedWrapper, this), + mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureWrapper, this) +{} + +CHIP_ERROR UniqueIdGetter::GetUniqueId(OnDoneCallback onDoneCallback, Controller::DeviceController & controller, NodeId nodeId, + EndpointId endpointId) +{ + assertChipStackLockedByCurrentThread(); + VerifyOrDie(!mCurrentlyGettingUid); + + mEndpointId = endpointId; + mOnDoneCallback = onDoneCallback; + mUniqueIdHasValue = false; + memset(mUniqueId, 0, sizeof(mUniqueId)); + mCurrentlyGettingUid = true; + + CHIP_ERROR err = controller.GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to connect to remote fabric sync bridge %" CHIP_ERROR_FORMAT, err.Format()); + mCurrentlyGettingUid = false; + } + return err; +} + +void UniqueIdGetter::OnAttributeData(const ConcreteDataAttributePath & path, TLV::TLVReader * data, const StatusIB & status) +{ + VerifyOrDie(path.mClusterId == Clusters::BridgedDeviceBasicInformation::Id); + + if (!status.IsSuccess()) + { + ChipLogError(NotSpecified, "Response Failure: %" CHIP_ERROR_FORMAT, status.ToChipError().Format()); + return; + } + + switch (path.mAttributeId) + { + case Clusters::BridgedDeviceBasicInformation::Attributes::UniqueID::Id: { + mUniqueIdHasValue = SuccessOrLog(data->GetString(mUniqueId, sizeof(mUniqueId)), "UniqueId"); + break; + } + default: + break; + } +} + +void UniqueIdGetter::OnError(CHIP_ERROR error) +{ + ChipLogProgress(NotSpecified, "Error Getting UID: %" CHIP_ERROR_FORMAT, error.Format()); +} + +void UniqueIdGetter::OnDone(ReadClient * apReadClient) +{ + mCurrentlyGettingUid = false; + mOnDoneCallback(mUniqueIdHasValue ? std::make_optional(mUniqueId) : std::nullopt); +} + +void UniqueIdGetter::OnDeviceConnected(Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle) +{ + VerifyOrDie(mCurrentlyGettingUid); + mClient = std::make_unique(app::InteractionModelEngine::GetInstance(), &exchangeMgr, *this /* callback */, + ReadClient::InteractionType::Read); + VerifyOrDie(mClient); + + AttributePathParams readPaths[1]; + readPaths[0] = AttributePathParams(mEndpointId, Clusters::BridgedDeviceBasicInformation::Id, + Clusters::BridgedDeviceBasicInformation::Attributes::UniqueID::Id); + + ReadPrepareParams readParams(sessionHandle); + + readParams.mpAttributePathParamsList = readPaths; + readParams.mAttributePathParamsListSize = 1; + + CHIP_ERROR err = mClient->SendRequest(readParams); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to read unique ID from the bridged device."); + OnDone(nullptr); + return; + } +} + +void UniqueIdGetter::OnDeviceConnectionFailure(const ScopedNodeId & peerId, CHIP_ERROR error) +{ + VerifyOrDie(mCurrentlyGettingUid); + ChipLogError(NotSpecified, "UniqueIdGetter failed to connect to " ChipLogFormatX64, ChipLogValueX64(peerId.GetNodeId())); + + OnDone(nullptr); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/UniqueIdGetter.h b/examples/fabric-sync/admin/UniqueIdGetter.h new file mode 100644 index 0000000000..eba4451599 --- /dev/null +++ b/examples/fabric-sync/admin/UniqueIdGetter.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include +#include + +#include +#include + +namespace admin { + +/** + * @brief Class used to get UniqueID from Bridged Device Basic Information Cluster + * + * When syncing a device from another fabric that does not have a UniqueID, spec + * dictates: + * When a Fabric Synchronizing Administrator commissions a Synchronized Device, + * it SHALL persist and maintain an association with the UniqueID in the Bridged + * Device Basic Information Cluster exposed by another Fabric Synchronizing + * Administrator. + * + * This class assists in retrieving the UniqueId in the above situation. + */ +class UniqueIdGetter : public chip::app::ReadClient::Callback +{ +public: + using OnDoneCallback = std::function)>; + + UniqueIdGetter(); + + CHIP_ERROR GetUniqueId(OnDoneCallback onDoneCallback, chip::Controller::DeviceController & controller, chip::NodeId nodeId, + chip::EndpointId endpointId); + + /////////////////////////////////////////////////////////////// + // ReadClient::Callback implementation + /////////////////////////////////////////////////////////////// + void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data, + const chip::app::StatusIB & status) override; + void OnError(CHIP_ERROR error) override; + void OnDone(chip::app::ReadClient * apReadClient) override; + + /////////////////////////////////////////////////////////////// + // callbacks for CASE session establishment + /////////////////////////////////////////////////////////////// + void OnDeviceConnected(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + void OnDeviceConnectionFailure(const chip::ScopedNodeId & peerId, CHIP_ERROR error); + +private: + std::unique_ptr mClient; + + OnDoneCallback mOnDoneCallback; + + chip::Callback::Callback mOnDeviceConnectedCallback; + chip::Callback::Callback mOnDeviceConnectionFailureCallback; + + bool mCurrentlyGettingUid = false; + bool mUniqueIdHasValue = false; + char mUniqueId[33]; + chip::EndpointId mEndpointId; +}; + +} // namespace admin diff --git a/examples/fabric-sync/bridge/BUILD.gn b/examples/fabric-sync/bridge/BUILD.gn index 310496bc54..8fb79b89f2 100644 --- a/examples/fabric-sync/bridge/BUILD.gn +++ b/examples/fabric-sync/bridge/BUILD.gn @@ -17,7 +17,11 @@ import("${chip_root}/src/app/chip_data_model.gni") import("${chip_root}/src/lib/lib.gni") config("config") { - include_dirs = [ "include" ] + include_dirs = [ + ".", + "${chip_root}/examples/common", + "${chip_root}/examples/platform/linux", + ] } chip_data_model("fabric-bridge-zap") { @@ -41,15 +45,22 @@ source_set("fabric-bridge-lib") { public_configs = [ ":config" ] sources = [ + "include/Bridge.h", "include/BridgedAdministratorCommissioning.h", "include/BridgedDevice.h", "include/BridgedDeviceBasicInformationImpl.h", "include/BridgedDeviceManager.h", "include/CHIPProjectAppConfig.h", + "include/CommissionerControlDelegate.h", + "include/FabricAdminDelegate.h", + "include/FabricBridge.h", + "src/Bridge.cpp", "src/BridgedAdministratorCommissioning.cpp", "src/BridgedDevice.cpp", "src/BridgedDeviceBasicInformationImpl.cpp", "src/BridgedDeviceManager.cpp", + "src/CommissionerControlDelegate.cpp", + "src/FabricBridge.cpp", ] deps = [ diff --git a/examples/fabric-sync/bridge/include/Bridge.h b/examples/fabric-sync/bridge/include/Bridge.h new file mode 100644 index 0000000000..d6ff91eded --- /dev/null +++ b/examples/fabric-sync/bridge/include/Bridge.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#pragma once + +#include "CommissionableInit.h" +#include "CommissionerControlDelegate.h" +#include "FabricAdminDelegate.h" + +namespace bridge { + +/** + * @brief Initializes the local fabric bridge system. + * + * This function sets up and initializes all necessary components required for + * device management and commissioning within the local fabric bridge. It interacts + * with the provided FabricAdminDelegate instance to manage fabric-level operations. + * Specifically, it registers command handlers, initializes device attributes, and + * prepares the bridge for commissioning operations. + * + * @param delegate A pointer to a FabricAdminDelegate instance, allowing the bridge + * to initialize and manage fabric operations. + * + * @return CHIP_NO_ERROR if all initializations are successful, or an appropriate + * CHIP_ERROR code if an initialization step fails. + */ +CHIP_ERROR BridgeInit(FabricAdminDelegate * delegate); + +/** + * @brief Shuts down the local fabric bridge system. + * + * This function performs cleanup operations and shuts down the bridge system components + * responsible for device management and commissioning. It stops the Commissioner Control + * Server and handles any errors that may occur during shutdown. + * + * @return CHIP_NO_ERROR if shutdown is successful, or an appropriate CHIP_ERROR code if any component fails to shut down. + */ +CHIP_ERROR BridgeShutdown(); + +} // namespace bridge diff --git a/examples/fabric-sync/bridge/include/BridgedDevice.h b/examples/fabric-sync/bridge/include/BridgedDevice.h index ed5c971062..903d853ec8 100644 --- a/examples/fabric-sync/bridge/include/BridgedDevice.h +++ b/examples/fabric-sync/bridge/include/BridgedDevice.h @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * diff --git a/examples/fabric-sync/bridge/include/BridgedDeviceManager.h b/examples/fabric-sync/bridge/include/BridgedDeviceManager.h index 6d17276766..be6c6a41db 100644 --- a/examples/fabric-sync/bridge/include/BridgedDeviceManager.h +++ b/examples/fabric-sync/bridge/include/BridgedDeviceManager.h @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * diff --git a/examples/fabric-sync/bridge/include/CHIPProjectAppConfig.h b/examples/fabric-sync/bridge/include/CHIPProjectAppConfig.h index 58f45c0305..ff6052169b 100644 --- a/examples/fabric-sync/bridge/include/CHIPProjectAppConfig.h +++ b/examples/fabric-sync/bridge/include/CHIPProjectAppConfig.h @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * diff --git a/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h b/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h new file mode 100644 index 0000000000..45a927307b --- /dev/null +++ b/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ +#pragma once + +#include "FabricAdminDelegate.h" + +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace CommissionerControl { + +inline constexpr EndpointId kAggregatorEndpointId = 1; + +class CommissionerControlDelegate : public Delegate +{ +public: + CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) : mFabricAdmin(fabricAdmin) {} + + CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; + // TODO(#35627) clientNodeId should move towards ScopedNodeId. + CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) override; + CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) override; + CHIP_ERROR HandleCommissionNode(const CommissioningWindowParams & params) override; + + ~CommissionerControlDelegate() = default; + +private: + enum class Step : uint8_t + { + // Ready to start reverse commissioning. + kIdle, + // Wait for the commission node command. + kWaitCommissionNodeRequest, + // Need to commission node. + kStartCommissionNode, + }; + + static const char * GetStateString(Step step) + { + switch (step) + { + case Step::kIdle: + return "kIdle"; + case Step::kWaitCommissionNodeRequest: + return "kWaitCommissionNodeRequest"; + case Step::kStartCommissionNode: + return "kStartCommissionNode"; + default: + return "Unknown"; + } + } + + void ResetDelegateState(); + + static constexpr size_t kLabelBufferSize = 64; + + Step mNextStep = Step::kIdle; + uint64_t mRequestId = 0; + NodeId mClientNodeId = kUndefinedNodeId; + VendorId mVendorId = VendorId::Unspecified; + uint16_t mProductId = 0; + char mLabelBuffer[kLabelBufferSize + 1]; + Optional mLabel; + + // Parameters needed for non-basic commissioning. + uint8_t mPBKDFSaltBuffer[Crypto::kSpake2p_Max_PBKDF_Salt_Length]; + ByteSpan mPBKDFSalt; + Crypto::Spake2pVerifierSerialized mPAKEPasscodeVerifierBuffer; + ByteSpan mPAKEPasscodeVerifier; + + bridge::FabricAdminDelegate * mFabricAdmin; +}; + +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + +namespace bridge { + +CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin); +CHIP_ERROR CommissionerControlShutdown(); + +} // namespace bridge diff --git a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h new file mode 100644 index 0000000000..8b67ffd5b2 --- /dev/null +++ b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace bridge { + +class FabricAdminDelegate +{ +public: + virtual ~FabricAdminDelegate() = default; + + /** + * Reverse commission a bridge using the specified parameters. + * + * This function initiates the commissioning process for a bridge node, utilizing + * the provided passcode parameters, vendor ID, and product ID. + * + * @param params Parameters required for commissioning the device using passcode. + * @param vendorId The Vendor ID (VID) of the device being commissioned. This identifies + * the manufacturer of the device. + * @param productId The Product ID (PID) of the device being commissioned. This identifies + * the specific product within the vendor's lineup. + * + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully sent and the commissioning process was initiated. + * - CHIP_ERROR_INTERNAL: An internal error occurred during the preparation or sending of the command. + */ + virtual CHIP_ERROR CommissionRemoteBridge(chip::Controller::CommissioningWindowPasscodeParams params, chip::VendorId vendorId, + uint16_t productId) = 0; + + virtual CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) = 0; +}; + +} // namespace bridge diff --git a/examples/fabric-sync/bridge/include/FabricBridge.h b/examples/fabric-sync/bridge/include/FabricBridge.h new file mode 100644 index 0000000000..48a3ddae4f --- /dev/null +++ b/examples/fabric-sync/bridge/include/FabricBridge.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#pragma once + +#include "FabricAdminDelegate.h" + +#include +#include +#include +#include +#include + +namespace bridge { + +#define ScopedNodeId_init_default chip::ScopedNodeId() +#define SynchronizedDevice_init_default \ + { \ + ScopedNodeId_init_default, /* id */ \ + std::nullopt, /* uniqueId */ \ + std::nullopt, /* vendorName */ \ + std::nullopt, /* vendorId */ \ + std::nullopt, /* productName */ \ + std::nullopt, /* productId */ \ + std::nullopt, /* nodeLabel */ \ + std::nullopt, /* hardwareVersion */ \ + std::nullopt, /* hardwareVersionString */ \ + std::nullopt, /* softwareVersion */ \ + std::nullopt, /* softwareVersionString */ \ + std::nullopt /* isIcd */ \ + } + +#define AdministratorCommissioningChanged_init_default \ + { \ + ScopedNodeId_init_default, /* id */ \ + chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kWindowNotOpen, /* windowStatus */ \ + std::nullopt, /* openerFabricIndex */ \ + std::nullopt /* openerVendorId */ \ + } + +struct SynchronizedDevice +{ + chip::ScopedNodeId id; + + std::optional uniqueId; + std::optional vendorName; + std::optional vendorId; + std::optional productName; + std::optional productId; + std::optional nodeLabel; + std::optional hardwareVersion; + std::optional hardwareVersionString; + std::optional softwareVersion; + std::optional softwareVersionString; + std::optional isIcd; +}; + +struct AdministratorCommissioningChanged +{ + chip::ScopedNodeId id; + chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum windowStatus; + std::optional openerFabricIndex; + std::optional openerVendorId; +}; + +class FabricBridge final +{ +public: + static FabricBridge & Instance(); + + void SetDelegate(FabricAdminDelegate * delegate) { mFabricAdmin = delegate; } + FabricAdminDelegate * GetDelegate() { return mFabricAdmin; } + + /** + * @brief Adds a synchronized device to the RPC client. + * + * This function attempts to add a device identified by its `nodeId` to the synchronized device list. + * It logs the progress and checks if an `AddSynchronizedDevice` operation is already in progress. + * If an operation is in progress, it returns `CHIP_ERROR_BUSY`. + * + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully processed. + * - CHIP_ERROR_BUSY: Another operation is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. + */ + CHIP_ERROR AddSynchronizedDevice(const SynchronizedDevice & data); + + /** + * @brief Removes a synchronized device from the RPC client. + * + * This function attempts to remove a device identified by its `nodeId` from the synchronized device list. + * It logs the progress and checks if a `RemoveSynchronizedDevice` operation is already in progress. + * If an operation is in progress, it returns `CHIP_ERROR_BUSY`. + * + * @param scopedNodeId The Scoped Node ID of the device to be removed. + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully processed. + * - CHIP_ERROR_BUSY: Another operation is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. + */ + CHIP_ERROR RemoveSynchronizedDevice(chip::ScopedNodeId scopedNodeId); + + /** + * @brief Received StayActiveResponse on behalf of client that previously called KeepActive + * + * @param scopedNodeId The Scoped Node ID of the device we recieved a StayActiveResponse. + * @param promisedActiveDurationMs the computed duration (in milliseconds) that the ICD intends to stay active for. + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully processed. + * - CHIP_ERROR_BUSY: Another operation is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. + */ + CHIP_ERROR ActiveChanged(chip::ScopedNodeId scopedNodeId, uint32_t promisedActiveDurationMs); + + /** + * @brief CADMIN attribute has changed of one of the bridged devices that was previously added. + * + * @param data information regarding change in AdministratorCommissioning attributes + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully processed. + * - CHIP_ERROR_BUSY: Another operation is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. + */ + CHIP_ERROR AdminCommissioningAttributeChanged(const AdministratorCommissioningChanged & data); + + /** + * @brief Notify the system that the reachability status of a bridged device has changed. + * + * @param scopedNodeId Identifier of the bridged device whose reachability has changed. + * @param reachability Boolean indicating the new reachability status of the device. + * - `true`: Device is reachable. + * - `false`: Device is not reachable. + * + * @return CHIP_ERROR Error code representing the outcome of the operation. + * - CHIP_NO_ERROR: The operation was successful. + * - CHIP_ERROR_BUSY: Another operation is currently in progress, preventing this action. + * - CHIP_ERROR_INTERNAL: An internal error occurred while processing the reachability change. + */ + CHIP_ERROR DeviceReachableChanged(chip::ScopedNodeId scopedNodeId, bool reachability); + +private: + static FabricBridge sInstance; + + FabricAdminDelegate * mFabricAdmin; +}; + +} // namespace bridge diff --git a/examples/fabric-sync/bridge/src/Bridge.cpp b/examples/fabric-sync/bridge/src/Bridge.cpp new file mode 100644 index 0000000000..02bda529ca --- /dev/null +++ b/examples/fabric-sync/bridge/src/Bridge.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "Bridge.h" + +#include "BridgedAdministratorCommissioning.h" +#include "BridgedDevice.h" +#include "BridgedDeviceBasicInformationImpl.h" +#include "BridgedDeviceManager.h" +#include "FabricBridge.h" + +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::AdministratorCommissioning; +using namespace chip::app::Clusters::BridgedDeviceBasicInformation; + +// This is declared here and not in a header because zap/embr assumes all clusters +// are defined in a static endpoint in the .zap file. From there, the codegen will +// automatically use PluginApplicationCallbacksHeader.jinja to declare and call +// the respective Init callbacks. However, because EcosystemInformation cluster is only +// ever on a dynamic endpoint, this doesn't get declared and called for us, so we +// need to declare and call it ourselves where the application is initialized. +void MatterEcosystemInformationPluginServerInitCallback(); + +namespace bridge { + +namespace { + +class BridgedDeviceInformationCommandHandler : public CommandHandlerInterface +{ +public: + // Register for the BridgedDeviceBasicInformation cluster on all endpoints. + BridgedDeviceInformationCommandHandler() : + CommandHandlerInterface(Optional::Missing(), BridgedDeviceBasicInformation::Id) + {} + + void InvokeCommand(HandlerContext & handlerContext) override; +}; + +void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & handlerContext) +{ + using Protocols::InteractionModel::Status; + VerifyOrReturn(handlerContext.mRequestPath.mCommandId == BridgedDeviceBasicInformation::Commands::KeepActive::Id); + + EndpointId endpointId = handlerContext.mRequestPath.mEndpointId; + ChipLogProgress(NotSpecified, "Received command to KeepActive on Endpoint: %d", endpointId); + + handlerContext.SetCommandHandled(); + + BridgedDeviceBasicInformation::Commands::KeepActive::DecodableType commandData; + if (DataModel::Decode(handlerContext.mPayload, commandData) != CHIP_NO_ERROR) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::InvalidCommand); + return; + } + + const uint32_t kMinTimeoutMs = 30 * 1000; + const uint32_t kMaxTimeoutMs = 60 * 60 * 1000; + if (commandData.timeoutMs < kMinTimeoutMs || commandData.timeoutMs > kMaxTimeoutMs) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::ConstraintError); + return; + } + + BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId); + if (device == nullptr || !device->IsIcd()) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::Failure); + return; + } + + Status status = Status::Failure; + FabricAdminDelegate * adminDelegate = FabricBridge::Instance().GetDelegate(); + + if (adminDelegate) + { + CHIP_ERROR err = + adminDelegate->KeepActive(device->GetScopedNodeId(), commandData.stayActiveDuration, commandData.timeoutMs); + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "KeepActive successfully processed"); + status = Status::Success; + } + else + { + ChipLogProgress(NotSpecified, "KeepActive failed to process: %s", ErrorStr(err)); + } + } + else + { + ChipLogProgress(NotSpecified, "Operation failed: adminDelegate is null"); + } + + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status); +} + +BridgedAdministratorCommissioning gBridgedAdministratorCommissioning; +BridgedDeviceBasicInformationImpl gBridgedDeviceBasicInformationAttributes; +BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler; + +} // namespace + +CHIP_ERROR BridgeInit(FabricAdminDelegate * delegate) +{ + MatterEcosystemInformationPluginServerInitCallback(); + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gBridgedDeviceInformationCommandHandler); + AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes); + + BridgeDeviceMgr().Init(); + FabricBridge::Instance().SetDelegate(delegate); + ReturnErrorOnFailure(gBridgedAdministratorCommissioning.Init()); + ReturnErrorOnFailure(CommissionerControlInit(delegate)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR BridgeShutdown() +{ + CHIP_ERROR err = CommissionerControlShutdown(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to shutdown Commissioner Control Server"); + } + + return err; +} + +} // namespace bridge diff --git a/examples/fabric-sync/bridge/src/BridgedDevice.cpp b/examples/fabric-sync/bridge/src/BridgedDevice.cpp index bd88c89145..1368f19bda 100644 --- a/examples/fabric-sync/bridge/src/BridgedDevice.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDevice.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp index 09c1b643c0..62d423dc9a 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * diff --git a/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp b/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp new file mode 100644 index 0000000000..12851177bc --- /dev/null +++ b/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "CommissionerControlDelegate.h" + +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; + +namespace { + +// Constants +constexpr uint16_t kDiscriminator = 3840; +constexpr uint16_t kWindowTimeout = 300; +constexpr uint16_t kIteration = 1000; +constexpr uint32_t kSetupPinCode = 20202021; + +std::unique_ptr sCommissionerControlDelegate; + +} // namespace + +namespace chip { +namespace app { +namespace Clusters { +namespace CommissionerControl { + +void CommissionerControlDelegate::ResetDelegateState() +{ + ChipLogProgress(NotSpecified, "CommissionerControlDelegate: Resetting delegate state"); + + // Reset the step to the initial state + mNextStep = Step::kIdle; + + // Reset identifiers and product information + mRequestId = 0; + mClientNodeId = kUndefinedNodeId; + mVendorId = VendorId::Unspecified; + mProductId = 0; + + // Clear the label buffer and optional label + memset(mLabelBuffer, 0, sizeof(mLabelBuffer)); + mLabel.ClearValue(); + + // Reset PBKDF salt and PAKE passcode verifier buffers + mPBKDFSalt = ByteSpan(); + memset(mPBKDFSaltBuffer, 0, sizeof(mPBKDFSaltBuffer)); + + mPAKEPasscodeVerifier = ByteSpan(); + memset(mPAKEPasscodeVerifierBuffer, 0, sizeof(mPAKEPasscodeVerifierBuffer)); +} + +CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) +{ + ChipLogProgress(NotSpecified, "CommissionerControlDelegate: Entering HandleCommissioningApprovalRequest, current state: %s", + GetStateString(mNextStep)); + + VerifyOrReturnError(mNextStep == Step::kIdle, CHIP_ERROR_INCORRECT_STATE); + + CommissionerControl::Events::CommissioningRequestResult::Type result; + result.requestID = request.requestId; + result.clientNodeID = request.clientNodeId; + result.fabricIndex = request.fabricIndex; + result.statusCode = static_cast(Protocols::InteractionModel::Status::Success); + + mRequestId = request.requestId; + mClientNodeId = request.clientNodeId; + mVendorId = request.vendorId; + mProductId = request.productId; + + if (request.label.HasValue()) + { + const CharSpan & labelSpan = request.label.Value(); + size_t labelLength = labelSpan.size(); + + if (labelLength >= kLabelBufferSize) + { + ChipLogError(Zcl, "Label too long to fit in buffer"); + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + if (labelLength == 0) + { + mLabel.ClearValue(); + } + else + { + memcpy(mLabelBuffer, labelSpan.data(), labelLength); + mLabelBuffer[labelLength] = '\0'; // Null-terminate the copied string + mLabel.SetValue(CharSpan(mLabelBuffer, labelLength)); + } + } + else + { + mLabel.ClearValue(); + } + + CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); + + if (err == CHIP_NO_ERROR) + { + mNextStep = Step::kWaitCommissionNodeRequest; + ChipLogProgress(NotSpecified, "CommissionerControlDelegate: State transitioned to %s", GetStateString(mNextStep)); + } + else + { + ResetDelegateState(); + } + + return err; +} + +CHIP_ERROR CommissionerControlDelegate::ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) +{ + ChipLogProgress(NotSpecified, "CommissionerControlDelegate: Entering ValidateCommissionNodeCommand, current state: %s", + GetStateString(mNextStep)); + + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrReturnError(mNextStep == Step::kWaitCommissionNodeRequest, CHIP_ERROR_INCORRECT_STATE); + + // Verify if the CommissionNode command is sent from the same NodeId as the RequestCommissioningApproval. + VerifyOrExit(mClientNodeId == clientNodeId, err = CHIP_ERROR_WRONG_NODE_ID); + + // Verify if the provided RequestId matches the value provided to the RequestCommissioningApproval. + VerifyOrExit(mRequestId == requestId, err = CHIP_ERROR_INCORRECT_STATE); + + mNextStep = Step::kStartCommissionNode; + ChipLogProgress(NotSpecified, "CommissionerControlDelegate: State transitioned to %s", GetStateString(mNextStep)); + +exit: + return err; +} + +CHIP_ERROR CommissionerControlDelegate::GetCommissioningWindowParams(CommissioningWindowParams & outParams) +{ + // Populate outParams with the required details. + outParams.iterations = kIteration; + outParams.commissioningTimeout = kWindowTimeout; + outParams.discriminator = kDiscriminator; + + ReturnErrorOnFailure(Crypto::DRBG_get_bytes(mPBKDFSaltBuffer, sizeof(mPBKDFSaltBuffer))); + mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer); + outParams.salt = mPBKDFSalt; + + Crypto::Spake2pVerifier verifier; + uint32_t setupPIN = kSetupPinCode; + ReturnErrorOnFailure(PASESession::GeneratePASEVerifier(verifier, kIteration, mPBKDFSalt, false, setupPIN)); + + MutableByteSpan serializedVerifierSpan(mPAKEPasscodeVerifierBuffer); + ReturnErrorOnFailure(verifier.Serialize(serializedVerifierSpan)); + mPAKEPasscodeVerifier = serializedVerifierSpan; + outParams.PAKEPasscodeVerifier = mPAKEPasscodeVerifier; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CommissionerControlDelegate::HandleCommissionNode(const CommissioningWindowParams & params) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + ChipLogProgress(NotSpecified, "CommissionerControlDelegate: Entering HandleCommissionNode, current state: %s", + GetStateString(mNextStep)); + + VerifyOrReturnError(mNextStep == Step::kStartCommissionNode, CHIP_ERROR_INCORRECT_STATE); + + // Attempt to reverse commission the bridge using provided commissioning parameters. + err = mFabricAdmin->CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParams() + .SetSetupPIN(kSetupPinCode) + .SetTimeout(params.commissioningTimeout) + .SetDiscriminator(params.discriminator) + .SetIteration(params.iterations) + .SetSalt(params.salt), + mVendorId, mProductId); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to reverse commission the fabric bridge. Error: %" CHIP_ERROR_FORMAT, err.Format()); + } + + // Reset the delegate's state to prepare for a new commissioning sequence. + ResetDelegateState(); + + return err; +} + +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + +namespace bridge { + +CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin) +{ + CHIP_ERROR err; + + if (sCommissionerControlDelegate) + { + ChipLogError(NotSpecified, "Commissioner Control Delegate already exists."); + return CHIP_ERROR_INCORRECT_STATE; + } + + sCommissionerControlDelegate = std::make_unique(fabricAdmin); + if (!sCommissionerControlDelegate) + { + ChipLogError(NotSpecified, "Failed to allocate memory for Commissioner Control Delegate."); + return CHIP_ERROR_NO_MEMORY; + } + + err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate."); + sCommissionerControlDelegate.reset(); + return err; + } + + ChipLogProgress(Zcl, "Initializing SupportedDeviceCategories of Commissioner Control Cluster for this device."); + + BitMask supportedDeviceCategories; + supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1); + + Protocols::InteractionModel::Status status = + Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue( + Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories); + + if (status != Protocols::InteractionModel::Status::Success) + { + ChipLogError(NotSpecified, "Failed to set SupportedDeviceCategories: %d", static_cast(status)); + sCommissionerControlDelegate.reset(); + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR CommissionerControlShutdown() +{ + if (sCommissionerControlDelegate) + { + sCommissionerControlDelegate.reset(); + } + + return CHIP_NO_ERROR; +} + +} // namespace bridge diff --git a/examples/fabric-sync/bridge/src/FabricBridge.cpp b/examples/fabric-sync/bridge/src/FabricBridge.cpp new file mode 100644 index 0000000000..d1c27d2409 --- /dev/null +++ b/examples/fabric-sync/bridge/src/FabricBridge.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "FabricBridge.h" +#include "BridgedDevice.h" +#include "BridgedDeviceManager.h" + +#include +#include + +#include +#include + +using namespace chip; + +namespace bridge { + +FabricBridge FabricBridge::sInstance; + +FabricBridge & FabricBridge::Instance() +{ + return sInstance; +} + +CHIP_ERROR FabricBridge::AddSynchronizedDevice(const SynchronizedDevice & data) +{ + ChipLogProgress(NotSpecified, "Received AddSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", data.id.GetFabricIndex(), + ChipLogValueX64(data.id.GetNodeId())); + + // Create a new BridgedDevice and set it as reachable + auto device = std::make_unique(data.id); + device->SetReachable(true); + + // Initialize BridgedDevice attributes from data + BridgedDevice::BridgedAttributes attributes; + + if (data.uniqueId.has_value()) + { + attributes.uniqueId = data.uniqueId.value(); + } + + if (data.vendorName.has_value()) + { + attributes.vendorName = data.vendorName.value(); + } + + if (data.vendorId.has_value()) + { + attributes.vendorId = data.vendorId.value(); + } + + if (data.productName.has_value()) + { + attributes.productName = data.productName.value(); + } + + if (data.productId.has_value()) + { + attributes.productId = data.productId.value(); + } + + if (data.nodeLabel.has_value()) + { + attributes.nodeLabel = data.nodeLabel.value(); + } + + if (data.hardwareVersion.has_value()) + { + attributes.hardwareVersion = data.hardwareVersion.value(); + } + + if (data.hardwareVersionString.has_value()) + { + attributes.hardwareVersionString = data.hardwareVersionString.value(); + } + + if (data.softwareVersion.has_value()) + { + attributes.softwareVersion = data.softwareVersion.value(); + } + + if (data.softwareVersionString.has_value()) + { + attributes.softwareVersionString = data.softwareVersionString.value(); + } + + // Set bridged device attributes and ICD status + device->SetBridgedAttributes(attributes); + device->SetIcd(data.isIcd.value_or(false)); + + // Add the device to the bridge manager with a parent endpoint + auto result = BridgeDeviceMgr().AddDeviceEndpoint(std::move(device), /* parentEndpointId= */ 1); + if (!result.has_value()) + { + ChipLogError(NotSpecified, "Failed to add device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(), + ChipLogValueX64(data.id.GetNodeId())); + return CHIP_ERROR_ENDPOINT_POOL_FULL; + } + + // Retrieve and verify the added device by ScopedNodeId + BridgedDevice * addedDevice = BridgeDeviceMgr().GetDeviceByScopedNodeId(data.id); + VerifyOrDie(addedDevice); + + ChipLogProgress(NotSpecified, "Added device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(), + ChipLogValueX64(data.id.GetNodeId())); + + // Add the Ecosystem Information Cluster to the device's endpoint + CHIP_ERROR err = + app::Clusters::EcosystemInformation::EcosystemInformationServer::Instance().AddEcosystemInformationClusterToEndpoint( + addedDevice->GetEndpointId()); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to add Ecosystem Information Cluster to endpoint %u: %" CHIP_ERROR_FORMAT, + addedDevice->GetEndpointId(), err.Format()); + } + + return err; +} + +CHIP_ERROR FabricBridge::RemoveSynchronizedDevice(ScopedNodeId scopedNodeId) +{ + ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), + ChipLogValueX64(scopedNodeId.GetNodeId())); + + auto removedIdx = BridgeDeviceMgr().RemoveDeviceByScopedNodeId(scopedNodeId); + if (!removedIdx.has_value()) + { + ChipLogError(NotSpecified, "Failed to remove device with Id=[%d:0x" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), + ChipLogValueX64(scopedNodeId.GetNodeId())); + return CHIP_ERROR_NOT_FOUND; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FabricBridge::ActiveChanged(ScopedNodeId scopedNodeId, uint32_t promisedActiveDurationMs) +{ + ChipLogProgress(NotSpecified, "Received ActiveChanged: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), + ChipLogValueX64(scopedNodeId.GetNodeId())); + + auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId); + if (device == nullptr) + { + ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", + scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); + return CHIP_ERROR_NOT_FOUND; + } + + device->LogActiveChangeEvent(promisedActiveDurationMs); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FabricBridge::AdminCommissioningAttributeChanged(const AdministratorCommissioningChanged & data) +{ + ChipLogProgress(NotSpecified, "Received CADMIN attribute change: Id=[%d:" ChipLogFormatX64 "]", data.id.GetFabricIndex(), + ChipLogValueX64(data.id.GetNodeId())); + + auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(data.id); + if (device == nullptr) + { + ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", + data.id.GetFabricIndex(), ChipLogValueX64(data.id.GetNodeId())); + return CHIP_ERROR_NOT_FOUND; + } + + BridgedDevice::AdminCommissioningAttributes adminCommissioningAttributes; + + VerifyOrReturnError(data.windowStatus < + app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kUnknownEnumValue, + CHIP_ERROR_INVALID_ARGUMENT); + + adminCommissioningAttributes.commissioningWindowStatus = data.windowStatus; + if (data.openerFabricIndex.has_value()) + { + VerifyOrReturnError(data.openerFabricIndex >= kMinValidFabricIndex, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(data.openerFabricIndex <= kMaxValidFabricIndex, CHIP_ERROR_INVALID_ARGUMENT); + adminCommissioningAttributes.openerFabricIndex = data.openerFabricIndex; + } + + if (data.openerVendorId.has_value()) + { + VerifyOrReturnError(data.openerVendorId != VendorId::NotSpecified, CHIP_ERROR_INVALID_ARGUMENT); + adminCommissioningAttributes.openerVendorId = data.openerVendorId; + } + + device->SetAdminCommissioningAttributes(adminCommissioningAttributes); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FabricBridge::DeviceReachableChanged(ScopedNodeId scopedNodeId, bool reachability) +{ + ChipLogProgress(NotSpecified, "Received device reachable changed: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), + ChipLogValueX64(scopedNodeId.GetNodeId())); + + auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId); + if (device == nullptr) + { + ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", + scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); + return CHIP_ERROR_NOT_FOUND; + } + + device->ReachableChanged(reachability); + + return CHIP_NO_ERROR; +} + +} // namespace bridge diff --git a/examples/fabric-sync/main.cpp b/examples/fabric-sync/main.cpp index 3cd5ab8c20..8772400ff2 100644 --- a/examples/fabric-sync/main.cpp +++ b/examples/fabric-sync/main.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * @@ -17,7 +16,9 @@ */ #include +#include #include +#include #if defined(ENABLE_CHIP_SHELL) #include "ShellCommands.h" @@ -82,12 +83,21 @@ void ApplicationInit() // Redirect logs to the custom logging callback Logging::SetLogRedirectCallback(LoggingCallback); + + CHIP_ERROR err = bridge::BridgeInit(&admin::FabricAdmin::Instance()); + VerifyOrDieWithMsg(err == CHIP_NO_ERROR, NotSpecified, "Fabric-Sync: Failed to initialize bridge, error: %s", ErrorStr(err)); } void ApplicationShutdown() { ChipLogDetail(NotSpecified, "Fabric-Sync: ApplicationShutdown()"); CloseLogFile(); + + CHIP_ERROR err = bridge::BridgeShutdown(); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Fabric-Sync: Failed to shutdown bridge, error: %s", ErrorStr(err)); + } } int main(int argc, char * argv[]) diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index 936ac1c321..4b70998dcc 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -54,6 +54,15 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) ChipLogValueX64(mBridgeNodeId)); admin::DeviceMgr().UpdateLastUsedNodeId(mBridgeNodeId); + admin::DeviceMgr().SubscribeRemoteFabricBridge(); + + // After successful commissioning of the Commissionee, initiate Reverse Commissioning + // via the Commissioner Control Cluster. However, we must first verify that the + // remote Fabric-Bridge supports Fabric Synchronization. + // + // Note: The Fabric-Admin MUST NOT send the RequestCommissioningApproval command + // if the remote Fabric-Bridge lacks Fabric Synchronization support. + DeviceLayer::SystemLayer().ScheduleLambda([]() { admin::DeviceMgr().ReadSupportedDeviceCategories(); }); } else { @@ -70,11 +79,14 @@ CHIP_ERROR AddBridgeCommand::RunCommand() { // print to console fprintf(stderr, "Remote Fabric Bridge has already been configured.\n"); - return CHIP_NO_ERROR; + return CHIP_ERROR_INCORRECT_STATE; } admin::PairingManager::Instance().SetPairingDelegate(this); + ChipLogProgress(NotSpecified, "Running AddBridgeCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mBridgeNodeId, + mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::DeviceMgr().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } diff --git a/examples/fabric-sync/shell/AddDeviceCommand.cpp b/examples/fabric-sync/shell/AddDeviceCommand.cpp index 218691e744..a85de7695d 100644 --- a/examples/fabric-sync/shell/AddDeviceCommand.cpp +++ b/examples/fabric-sync/shell/AddDeviceCommand.cpp @@ -71,6 +71,9 @@ CHIP_ERROR AddDeviceCommand::RunCommand() return CHIP_ERROR_INVALID_ARGUMENT; } + ChipLogProgress(NotSpecified, "Running AddDeviceCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mNodeId, + mSetupPINCode, mRemoteAddr, mRemotePort); + admin::PairingManager::Instance().SetPairingDelegate(this); return admin::DeviceMgr().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); diff --git a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp index 2eaaf6fc34..77bd76be33 100644 --- a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp +++ b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp @@ -57,11 +57,13 @@ CHIP_ERROR RemoveBridgeCommand::RunCommand() { // print to console fprintf(stderr, "Remote Fabric Bridge is not configured yet, nothing to remove.\n"); - return CHIP_NO_ERROR; + return CHIP_ERROR_INCORRECT_STATE; } mBridgeNodeId = bridgeNodeId; + ChipLogProgress(NotSpecified, "Running RemoveBridgeCommand"); + admin::PairingManager::Instance().SetPairingDelegate(this); return admin::DeviceMgr().UnpairRemoteFabricBridge(); diff --git a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp index 266a2ad106..78440f8542 100644 --- a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp +++ b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp @@ -61,6 +61,8 @@ CHIP_ERROR RemoveDeviceCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); + ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: %lu", mNodeId); + return admin::DeviceMgr().UnpairRemoteDevice(mNodeId); } diff --git a/examples/fabric-sync/shell/ShellCommands.cpp b/examples/fabric-sync/shell/ShellCommands.cpp index fa859a34d5..3bab442aa5 100644 --- a/examples/fabric-sync/shell/ShellCommands.cpp +++ b/examples/fabric-sync/shell/ShellCommands.cpp @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -134,7 +133,7 @@ static CHIP_ERROR HandleAddDeviceCommand(int argc, char ** argv) const char * remoteAddr = argv[3]; uint16_t remotePort = static_cast(strtoul(argv[4], nullptr, 10)); - auto command = std::make_unique(nodeId, setupPINCode, remoteAddr, remotePort); + auto command = std::make_unique(nodeId, setupPINCode, remoteAddr, remotePort); CHIP_ERROR result = command->RunCommand(); if (result == CHIP_NO_ERROR) diff --git a/examples/fabric-sync/shell/ShellCommands.h b/examples/fabric-sync/shell/ShellCommands.h index ab957bc8cd..b5bd5085fb 100644 --- a/examples/fabric-sync/shell/ShellCommands.h +++ b/examples/fabric-sync/shell/ShellCommands.h @@ -1,5 +1,4 @@ /* - * * Copyright (c) 2024 Project CHIP Authors * All rights reserved. * From 9a68d629e43d188d5609dbdad36cfb1b494c20dc Mon Sep 17 00:00:00 2001 From: andrei-menzopol <96489227+andrei-menzopol@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:20:32 +0200 Subject: [PATCH 004/219] [nxp][examples][mcxw71_k32w1] Add platform/CHIPDeviceBuildConfig.h (#36482) * [nxp][examples][mcxw71_k32w1] Include platform/CHIPDeviceConfig.h in FreeRtosHooks.cpp * this will include the CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR macro allowing OTAIdleActivities to be called during ota. * Switch FreeRtosHooks.c to FreeRtosHooks.cpp * Add extern to functions Signed-off-by: Andrei Menzopol * Restyled by whitespace * Restyled by clang-format * Restyled by gn --------- Signed-off-by: Andrei Menzopol Co-authored-by: Restyled.io --- .../platform/nxp/mcxw71_k32w1/app/support/BUILD.gn | 13 +++++++++---- .../support/{FreeRtosHooks.c => FreeRtosHooks.cpp} | 9 ++++++++- .../nxp/mcxw71_k32w1/app/support/FreeRtosHooks.h | 12 +++++------- 3 files changed, 22 insertions(+), 12 deletions(-) rename examples/platform/nxp/mcxw71_k32w1/app/support/{FreeRtosHooks.c => FreeRtosHooks.cpp} (95%) diff --git a/examples/platform/nxp/mcxw71_k32w1/app/support/BUILD.gn b/examples/platform/nxp/mcxw71_k32w1/app/support/BUILD.gn index d49e9e7638..1034d91feb 100644 --- a/examples/platform/nxp/mcxw71_k32w1/app/support/BUILD.gn +++ b/examples/platform/nxp/mcxw71_k32w1/app/support/BUILD.gn @@ -42,12 +42,14 @@ config("support_config") { source_set("freertos_memory_utils") { sources = [ - "FreeRtosHooks.c", - "FreeRtosHooks.h", + "FreeRtosHooks.cpp", "Memconfig.cpp", ] - deps = [ "${chip_root}/src/lib/support" ] + deps = [ + "${chip_root}/src/lib/support", + "${chip_root}/src/platform:platform_config_header", + ] cflags = [ "-Wconversion" ] @@ -57,5 +59,8 @@ source_set("freertos_memory_utils") { defines = [ "CHIP_PLAT_NVM_SUPPORT=3" ] } - public_configs = [ ":support_config" ] + public_configs = [ + ":support_config", + "${chip_root}/src:includes", + ] } diff --git a/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.c b/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.cpp similarity index 95% rename from examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.c rename to examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.cpp index bc5acf2e88..193b262231 100644 --- a/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.c +++ b/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.cpp @@ -27,6 +27,9 @@ #include #include +/* Include CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR */ +#include + #if (CHIP_PLAT_NVM_SUPPORT == 1) #include "NVM_Interface.h" #elif (CHIP_PLAT_NVM_SUPPORT == 3) @@ -55,6 +58,8 @@ #define APP_DBG_LOG(...) #endif +extern "C" { + static inline void mutex_init(mbedtls_threading_mutex_t * p_mutex) { assert(p_mutex != NULL); @@ -73,7 +78,7 @@ static inline int mutex_lock(mbedtls_threading_mutex_t * p_mutex) { assert(p_mutex != NULL); assert(*p_mutex != NULL); - return xSemaphoreTake(*p_mutex, portMAX_DELAY) != pdTRUE; + return xSemaphoreTake((SemaphoreHandle_t) (*p_mutex), portMAX_DELAY) != pdTRUE; } static inline int mutex_unlock(mbedtls_threading_mutex_t * p_mutex) @@ -153,3 +158,5 @@ void vApplicationIdleHook(void) OTAIdleActivities(); #endif } + +} // extern "C" diff --git a/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.h b/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.h index a27f72d498..963b38973d 100644 --- a/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.h +++ b/examples/platform/nxp/mcxw71_k32w1/app/support/FreeRtosHooks.h @@ -20,17 +20,15 @@ typedef void * mbedtls_threading_mutex_t; -extern void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), - void (*mutex_free)(mbedtls_threading_mutex_t *), - int (*mutex_lock)(mbedtls_threading_mutex_t *), - int (*mutex_unlock)(mbedtls_threading_mutex_t *)); - -extern void mbedtls_threading_free_alt(void); - #ifdef __cplusplus extern "C" { #endif +void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), void (*mutex_free)(mbedtls_threading_mutex_t *), + int (*mutex_lock)(mbedtls_threading_mutex_t *), int (*mutex_unlock)(mbedtls_threading_mutex_t *)); + +void mbedtls_threading_free_alt(void); + /**@brief Function for initializing alternative MbedTLS mutexes to enable the usage of the FreeRTOS implementation. */ void freertos_mbedtls_mutex_init(void); From acea4646d980196f3298129d9fdef76238f2f238 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Thu, 14 Nov 2024 08:35:30 -0500 Subject: [PATCH 005/219] Move ember-specific attribute persistence providers into `src/util/persistence` (#36473) * Move persistence providers code into util since they depend on ember. Unit tests pass, will need to fix up apps. * Fix up more includes * Restyled by clang-format * Fix up qpg build * Also fix nrfconnect deferred attribute persistence use * Fix path * Add persistence to esp32 CMakeLists.txt * Update examples/lighting-app/qpg/BUILD.gn --------- Co-authored-by: Andrei Litvin Co-authored-by: Restyled.io --- .../esp32/main/CMakeLists.txt | 1 + .../esp32/main/CMakeLists.txt | 1 + examples/bridge-app/esp32/main/CMakeLists.txt | 1 + examples/chef/esp32/main/CMakeLists.txt | 1 + .../esp32/main/CMakeLists.txt | 1 + .../esp32/main/CMakeLists.txt | 1 + .../lighting-app/esp32/main/CMakeLists.txt | 1 + .../lighting-app/nrfconnect/CMakeLists.txt | 1 + .../lighting-app/nrfconnect/main/AppTask.cpp | 2 +- examples/lighting-app/qpg/BUILD.gn | 1 + examples/lighting-app/qpg/src/AppTask.cpp | 2 +- .../lit-icd-app/esp32/main/CMakeLists.txt | 1 + examples/lock-app/esp32/main/CMakeLists.txt | 2 + .../esp32/main/CMakeLists.txt | 1 + .../esp32/main/CMakeLists.txt | 1 + .../esp32/main/CMakeLists.txt | 1 + .../thread-br-app/esp32/main/CMakeLists.txt | 1 + src/BUILD.gn | 5 +- src/app/BUILD.gn | 18 ++++--- src/app/SafeAttributePersistenceProvider.h | 5 +- src/app/chip_data_model.cmake | 1 + src/app/chip_data_model.gni | 1 + .../mode-base-server/mode-base-server.h | 2 +- src/app/server/BUILD.gn | 1 + src/app/server/Server.h | 6 ++- src/app/tests/BUILD.gn | 1 - src/app/util/attribute-storage.cpp | 2 +- .../AttributePersistenceProvider.h | 0 src/app/util/persistence/BUILD.gn | 47 +++++++++++++++++++ .../DefaultAttributePersistenceProvider.cpp | 2 +- .../DefaultAttributePersistenceProvider.h | 2 +- .../DeferredAttributePersistenceProvider.cpp | 2 +- .../DeferredAttributePersistenceProvider.h | 2 +- src/app/util/persistence/tests/BUILD.gn | 34 ++++++++++++++ .../TestAttributePersistenceProvider.cpp | 2 +- 35 files changed, 133 insertions(+), 20 deletions(-) rename src/app/{ => util/persistence}/AttributePersistenceProvider.h (100%) create mode 100644 src/app/util/persistence/BUILD.gn rename src/app/{ => util/persistence}/DefaultAttributePersistenceProvider.cpp (98%) rename src/app/{ => util/persistence}/DefaultAttributePersistenceProvider.h (97%) rename src/app/{ => util/persistence}/DeferredAttributePersistenceProvider.cpp (97%) rename src/app/{ => util/persistence}/DeferredAttributePersistenceProvider.h (98%) create mode 100644 src/app/util/persistence/tests/BUILD.gn rename src/app/{ => util/persistence}/tests/TestAttributePersistenceProvider.cpp (99%) diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 31292543ca..c35efdf4de 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -45,6 +45,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util/persistence" "${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/air-quality-server" diff --git a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt index f82f301e3a..680d4a9c02 100644 --- a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt @@ -38,6 +38,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util/persistence" "${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/application-basic-server" diff --git a/examples/bridge-app/esp32/main/CMakeLists.txt b/examples/bridge-app/esp32/main/CMakeLists.txt index 3330f6971b..9d34b44a92 100644 --- a/examples/bridge-app/esp32/main/CMakeLists.txt +++ b/examples/bridge-app/esp32/main/CMakeLists.txt @@ -23,6 +23,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/chef/esp32/main/CMakeLists.txt b/examples/chef/esp32/main/CMakeLists.txt index 5c8963f773..a7905ff214 100644 --- a/examples/chef/esp32/main/CMakeLists.txt +++ b/examples/chef/esp32/main/CMakeLists.txt @@ -79,6 +79,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" ) diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index e545961623..06623d3faf 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -44,6 +44,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/light-switch-app/esp32/main/CMakeLists.txt b/examples/light-switch-app/esp32/main/CMakeLists.txt index b4b6f5946e..92be83565a 100644 --- a/examples/light-switch-app/esp32/main/CMakeLists.txt +++ b/examples/light-switch-app/esp32/main/CMakeLists.txt @@ -30,6 +30,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" diff --git a/examples/lighting-app/esp32/main/CMakeLists.txt b/examples/lighting-app/esp32/main/CMakeLists.txt index d3dc3421cc..1ad5bc1aa3 100644 --- a/examples/lighting-app/esp32/main/CMakeLists.txt +++ b/examples/lighting-app/esp32/main/CMakeLists.txt @@ -34,6 +34,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 59bf2f26be..dd5b65afe6 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -51,6 +51,7 @@ target_sources(app PRIVATE main/AppTask.cpp main/main.cpp main/ZclCallbacks.cpp + ${CHIP_ROOT}/src/app/util/persistence/DeferredAttributePersistenceProvider.cpp ${NRFCONNECT_COMMON}/util/LEDWidget.cpp ${NRFCONNECT_COMMON}/util/PWMDevice.cpp) diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index 88964d9aa1..014849780c 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -26,13 +26,13 @@ #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/examples/lighting-app/qpg/BUILD.gn b/examples/lighting-app/qpg/BUILD.gn index 886c8aa313..b4a2998f02 100644 --- a/examples/lighting-app/qpg/BUILD.gn +++ b/examples/lighting-app/qpg/BUILD.gn @@ -66,6 +66,7 @@ qpg_executable("lighting_app") { "${chip_root}/examples/lighting-app/lighting-common:color-format", "${chip_root}/examples/lighting-app/qpg/zap/", "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app/util/persistence:deferred", "${chip_root}/src/lib", "${chip_root}/src/platform/logging:default", "${chip_root}/src/setup_payload", diff --git a/examples/lighting-app/qpg/src/AppTask.cpp b/examples/lighting-app/qpg/src/AppTask.cpp index 90f2e30ecb..0c09e97a6a 100644 --- a/examples/lighting-app/qpg/src/AppTask.cpp +++ b/examples/lighting-app/qpg/src/AppTask.cpp @@ -43,7 +43,7 @@ #include #include -#include +#include #include #include diff --git a/examples/lit-icd-app/esp32/main/CMakeLists.txt b/examples/lit-icd-app/esp32/main/CMakeLists.txt index 5f2850feff..4d8fe2ab4b 100644 --- a/examples/lit-icd-app/esp32/main/CMakeLists.txt +++ b/examples/lit-icd-app/esp32/main/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index 5c5f46abdd..028a92ae8d 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -49,6 +49,7 @@ idf_component_register(INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" @@ -162,6 +163,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" diff --git a/examples/ota-provider-app/esp32/main/CMakeLists.txt b/examples/ota-provider-app/esp32/main/CMakeLists.txt index 41acd9e931..d651ac7706 100644 --- a/examples/ota-provider-app/esp32/main/CMakeLists.txt +++ b/examples/ota-provider-app/esp32/main/CMakeLists.txt @@ -26,6 +26,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/ota-requestor-app/esp32/main/CMakeLists.txt b/examples/ota-requestor-app/esp32/main/CMakeLists.txt index fbda70f2ce..2688fea497 100644 --- a/examples/ota-requestor-app/esp32/main/CMakeLists.txt +++ b/examples/ota-requestor-app/esp32/main/CMakeLists.txt @@ -31,6 +31,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt index 8bc94f7b97..8036700df6 100644 --- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt @@ -29,6 +29,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" diff --git a/examples/thread-br-app/esp32/main/CMakeLists.txt b/examples/thread-br-app/esp32/main/CMakeLists.txt index c0cb1234b0..c1f82285e4 100644 --- a/examples/thread-br-app/esp32/main/CMakeLists.txt +++ b/examples/thread-br-app/esp32/main/CMakeLists.txt @@ -30,6 +30,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" "${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/util/persistence" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" diff --git a/src/BUILD.gn b/src/BUILD.gn index 722e0c8278..3676c92c97 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -100,7 +100,10 @@ if (chip_build_tests) { } if (chip_device_platform != "efr32") { - tests += [ "${chip_root}/src/app/tests" ] + tests += [ + "${chip_root}/src/app/tests", + "${chip_root}/src/app/util/persistence/tests", + ] # Disabled for EFR32 because _open is not implemented. # https://github.com/project-chip/connectedhomeip/issues/35624 diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index b0cde0960c..8b008c4e9b 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -389,6 +389,18 @@ source_set("command-handler-impl") { ] } +source_set("attribute-persistence") { + sources = [ "SafeAttributePersistenceProvider.h" ] + + public_deps = [ + ":paths", + "${chip_root}/src/app/data-model:nullable", + "${chip_root}/src/app/util:types", + "${chip_root}/src/lib/support", + "${chip_root}/src/lib/support:span", + ] +} + # Note to developpers, instead of continuously adding files in the app librabry, it is recommand to create smaller source_sets that app can depend on. # This way, we can have a better understanding of dependencies and other componenets can depend on the different source_sets without needing to depend on the entire app library. static_library("app") { @@ -398,15 +410,10 @@ static_library("app") { "AttributePathExpandIterator.cpp", "AttributePathExpandIterator.h", "AttributePathExpandIterator.h", - "AttributePersistenceProvider.h", "ChunkedWriteCallback.cpp", "ChunkedWriteCallback.h", "CommandResponseHelper.h", "CommandResponseSender.cpp", - "DefaultAttributePersistenceProvider.cpp", - "DefaultAttributePersistenceProvider.h", - "DeferredAttributePersistenceProvider.cpp", - "DeferredAttributePersistenceProvider.h", "EventLogging.h", "EventManagement.cpp", "EventManagement.h", @@ -416,7 +423,6 @@ static_library("app") { "GenericEventManagementTestEventTriggerHandler.h", "OTAUserConsentCommon.h", "ReadHandler.cpp", - "SafeAttributePersistenceProvider.h", "TimerDelegates.cpp", "TimerDelegates.h", "WriteHandler.cpp", diff --git a/src/app/SafeAttributePersistenceProvider.h b/src/app/SafeAttributePersistenceProvider.h index 8d11d95d47..b1e7148c79 100644 --- a/src/app/SafeAttributePersistenceProvider.h +++ b/src/app/SafeAttributePersistenceProvider.h @@ -18,12 +18,13 @@ #include #include #include -#include -#include #include #include #include +#include +#include + namespace chip { namespace app { diff --git a/src/app/chip_data_model.cmake b/src/app/chip_data_model.cmake index 75e2d8a349..0f62842895 100644 --- a/src/app/chip_data_model.cmake +++ b/src/app/chip_data_model.cmake @@ -164,6 +164,7 @@ function(chip_configure_data_model APP_TARGET) ${CHIP_APP_BASE_DIR}/util/generic-callback-stubs.cpp ${CHIP_APP_BASE_DIR}/util/privilege-storage.cpp ${CHIP_APP_BASE_DIR}/util/util.cpp + ${CHIP_APP_BASE_DIR}/util/persistence/DefaultAttributePersistenceProvider.cpp ${CODEGEN_DATA_MODEL_SOURCES} ${APP_GEN_FILES} ${APP_TEMPLATES_GEN_FILES} diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 9f4ed594cc..3be8df5710 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -460,6 +460,7 @@ template("chip_data_model") { "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/app/common:enums", "${chip_root}/src/app/util:types", + "${chip_root}/src/app/util/persistence", "${chip_root}/src/controller", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", diff --git a/src/app/clusters/mode-base-server/mode-base-server.h b/src/app/clusters/mode-base-server/mode-base-server.h index f787e9fc19..06c22f3a42 100644 --- a/src/app/clusters/mode-base-server/mode-base-server.h +++ b/src/app/clusters/mode-base-server/mode-base-server.h @@ -20,8 +20,8 @@ #include "mode-base-cluster-objects.h" #include -#include #include +#include #include namespace chip { diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index 42c4caf05c..43c970843b 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -58,6 +58,7 @@ static_library("server") { "${chip_root}/src/app:test-event-trigger", "${chip_root}/src/app/icd/server:icd-server-config", "${chip_root}/src/app/icd/server:observer", + "${chip_root}/src/app/util/persistence", "${chip_root}/src/lib/address_resolve", "${chip_root}/src/lib/dnssd", "${chip_root}/src/lib/dnssd:naming", diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 2f61197fce..fc6f7ac107 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -81,6 +80,11 @@ #endif // CHIP_CONFIG_ENABLE_ICD_CIP #endif // CHIP_CONFIG_ENABLE_ICD_SERVER +// TODO: https://github.com/project-chip/connectedhomeip/issues/36472 +// this strongly couples Server to Ember and this dependency should +// be removed +#include + namespace chip { inline constexpr size_t kMaxBlePendingPackets = 1; diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 6f55c7bb6f..105d09f7ad 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -198,7 +198,6 @@ chip_test_suite("tests") { "TestAttributeAccessInterfaceCache.cpp", "TestAttributePathExpandIterator.cpp", "TestAttributePathParams.cpp", - "TestAttributePersistenceProvider.cpp", "TestAttributeValueDecoder.cpp", "TestAttributeValueEncoder.cpp", "TestBasicCommandPathRegistry.cpp", diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index 51c01c7e43..4d9cc2368f 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -28,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/src/app/AttributePersistenceProvider.h b/src/app/util/persistence/AttributePersistenceProvider.h similarity index 100% rename from src/app/AttributePersistenceProvider.h rename to src/app/util/persistence/AttributePersistenceProvider.h diff --git a/src/app/util/persistence/BUILD.gn b/src/app/util/persistence/BUILD.gn new file mode 100644 index 0000000000..dbc8dbe31b --- /dev/null +++ b/src/app/util/persistence/BUILD.gn @@ -0,0 +1,47 @@ +# Copyright (c) 2024 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. + +import("//build_overrides/chip.gni") + +source_set("persistence") { + sources = [ + "AttributePersistenceProvider.h", + "DefaultAttributePersistenceProvider.cpp", + "DefaultAttributePersistenceProvider.h", + ] + + public_deps = [ + "${chip_root}/src/app:attribute-persistence", + "${chip_root}/src/app:paths", + "${chip_root}/src/app/util:types", + "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", + "${chip_root}/src/lib/support:span", + ] +} + +source_set("deferred") { + sources = [ + "DeferredAttributePersistenceProvider.cpp", + "DeferredAttributePersistenceProvider.h", + ] + + public_deps = [ + ":persistence", + "${chip_root}/src/lib/support", + "${chip_root}/src/lib/support:span", + "${chip_root}/src/platform", + "${chip_root}/src/system", + ] +} diff --git a/src/app/DefaultAttributePersistenceProvider.cpp b/src/app/util/persistence/DefaultAttributePersistenceProvider.cpp similarity index 98% rename from src/app/DefaultAttributePersistenceProvider.cpp rename to src/app/util/persistence/DefaultAttributePersistenceProvider.cpp index 40ce521362..70488e80e7 100644 --- a/src/app/DefaultAttributePersistenceProvider.cpp +++ b/src/app/util/persistence/DefaultAttributePersistenceProvider.cpp @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include -#include #include #include #include diff --git a/src/app/DefaultAttributePersistenceProvider.h b/src/app/util/persistence/DefaultAttributePersistenceProvider.h similarity index 97% rename from src/app/DefaultAttributePersistenceProvider.h rename to src/app/util/persistence/DefaultAttributePersistenceProvider.h index 3e18808f36..a4796f2b63 100644 --- a/src/app/DefaultAttributePersistenceProvider.h +++ b/src/app/util/persistence/DefaultAttributePersistenceProvider.h @@ -15,8 +15,8 @@ */ #pragma once -#include #include +#include #include #include diff --git a/src/app/DeferredAttributePersistenceProvider.cpp b/src/app/util/persistence/DeferredAttributePersistenceProvider.cpp similarity index 97% rename from src/app/DeferredAttributePersistenceProvider.cpp rename to src/app/util/persistence/DeferredAttributePersistenceProvider.cpp index 26adcb18c8..6b1822f292 100644 --- a/src/app/DeferredAttributePersistenceProvider.cpp +++ b/src/app/util/persistence/DeferredAttributePersistenceProvider.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include +#include #include diff --git a/src/app/DeferredAttributePersistenceProvider.h b/src/app/util/persistence/DeferredAttributePersistenceProvider.h similarity index 98% rename from src/app/DeferredAttributePersistenceProvider.h rename to src/app/util/persistence/DeferredAttributePersistenceProvider.h index 6c641dc17d..592408b96b 100644 --- a/src/app/DeferredAttributePersistenceProvider.h +++ b/src/app/util/persistence/DeferredAttributePersistenceProvider.h @@ -15,7 +15,7 @@ */ #pragma once -#include +#include #include #include #include diff --git a/src/app/util/persistence/tests/BUILD.gn b/src/app/util/persistence/tests/BUILD.gn new file mode 100644 index 0000000000..7a0bd52430 --- /dev/null +++ b/src/app/util/persistence/tests/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright (c) 2024 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. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("//build_overrides/pigweed.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libAppUtilPersistenceTests" + + test_sources = [ "TestAttributePersistenceProvider.cpp" ] + + cflags = [ "-Wconversion" ] + + public_deps = [ + "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/src/app/util/persistence", + "${chip_root}/src/lib/core:string-builder-adapters", + "${chip_root}/src/lib/support:testing", + ] +} diff --git a/src/app/tests/TestAttributePersistenceProvider.cpp b/src/app/util/persistence/tests/TestAttributePersistenceProvider.cpp similarity index 99% rename from src/app/tests/TestAttributePersistenceProvider.cpp rename to src/app/util/persistence/tests/TestAttributePersistenceProvider.cpp index 1b8c7ee3d3..1324f37a71 100644 --- a/src/app/tests/TestAttributePersistenceProvider.cpp +++ b/src/app/util/persistence/tests/TestAttributePersistenceProvider.cpp @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include #include From 355a2a63c260991156327f80d44a284b48530679 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 09:44:34 -0800 Subject: [PATCH 006/219] Add timeout to excute a command (#36492) --- examples/fabric-sync/shell/BUILD.gn | 1 + .../fabric-sync/shell/CommandRegistry.cpp | 48 +++++++++++++++++++ examples/fabric-sync/shell/CommandRegistry.h | 11 ++++- 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 examples/fabric-sync/shell/CommandRegistry.cpp diff --git a/examples/fabric-sync/shell/BUILD.gn b/examples/fabric-sync/shell/BUILD.gn index b3726ee178..436f8b5160 100644 --- a/examples/fabric-sync/shell/BUILD.gn +++ b/examples/fabric-sync/shell/BUILD.gn @@ -31,6 +31,7 @@ source_set("shell") { "AddBridgeCommand.h", "AddDeviceCommand.cpp", "AddDeviceCommand.h", + "CommandRegistry.cpp", "CommandRegistry.h", "RemoveBridgeCommand.cpp", "RemoveBridgeCommand.h", diff --git a/examples/fabric-sync/shell/CommandRegistry.cpp b/examples/fabric-sync/shell/CommandRegistry.cpp new file mode 100644 index 0000000000..34c01357ea --- /dev/null +++ b/examples/fabric-sync/shell/CommandRegistry.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "CommandRegistry.h" + +#include + +using namespace ::chip; + +namespace commands { + +void CommandRegistry::SetActiveCommand(std::unique_ptr command, uint32_t timeoutSeconds) +{ + mActiveCommand = std::move(command); + + // Cancel any previous timer to avoid multiple timers running simultaneously + DeviceLayer::SystemLayer().CancelTimer(OnTimeout, this); + + // Start a new timer for the specified timeout + CHIP_ERROR err = DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(timeoutSeconds * 1000), OnTimeout, this); + if (err != CHIP_NO_ERROR) + { + ResetActiveCommand(); + } +} + +void CommandRegistry::ResetActiveCommand() +{ + DeviceLayer::SystemLayer().CancelTimer(OnTimeout, this); + mActiveCommand.reset(); +} + +} // namespace commands diff --git a/examples/fabric-sync/shell/CommandRegistry.h b/examples/fabric-sync/shell/CommandRegistry.h index ec53e17960..0043c267a5 100644 --- a/examples/fabric-sync/shell/CommandRegistry.h +++ b/examples/fabric-sync/shell/CommandRegistry.h @@ -38,16 +38,23 @@ class CommandRegistry return instance; } - void SetActiveCommand(std::unique_ptr command) { mActiveCommand = std::move(command); } + void SetActiveCommand(std::unique_ptr command, uint32_t timeoutSeconds = 30); Command * GetActiveCommand() { return mActiveCommand.get(); } - void ResetActiveCommand() { mActiveCommand.reset(); } + void ResetActiveCommand(); bool IsCommandActive() const { return mActiveCommand != nullptr; } private: CommandRegistry() = default; + + static void OnTimeout(chip::System::Layer * layer, void * appState) + { + // Callback function to reset the command when the timer expires + static_cast(appState)->ResetActiveCommand(); + } + std::unique_ptr mActiveCommand; }; From 238493fc20e63edcbfbe2c4f6d8e1f5e004aa831 Mon Sep 17 00:00:00 2001 From: Hasty Granbery Date: Thu, 14 Nov 2024 10:51:06 -0800 Subject: [PATCH 007/219] [HVAC] Thermostat deadband handling (#35673) * [HVAC] Shift heating and cooling setpoints to preserve deadband, when possible * Minor function renames, fix incorrect setters * Populate deadband on setpointLimits when Auto is supported * [Thermostat] Add test for deadband handling * Restyled Python test * Fix int promotion errors on some platforms * Remove unused Python imports * Fix capitalization of structs, methods, fields, etc. * Silly C++ int promotion rules * [HVAC] Fix incorrect naming of TSTAT 2.3 test class * Fix errant quote in TC_TSTAT_2_3.py * Drop deadband fix test in favor of separate PR * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Don't use three-arg setter for attributes * Rename deadband member * Add backwards-compatibility comment for return code substitution * Restyled --------- Co-authored-by: Boris Zbarsky --- .../thermostat-server/thermostat-server.cpp | 348 +++++++++++++++--- 1 file changed, 307 insertions(+), 41 deletions(-) diff --git a/src/app/clusters/thermostat-server/thermostat-server.cpp b/src/app/clusters/thermostat-server/thermostat-server.cpp index bda97c5cb1..a1f0d27779 100644 --- a/src/app/clusters/thermostat-server/thermostat-server.cpp +++ b/src/app/clusters/thermostat-server/thermostat-server.cpp @@ -220,6 +220,292 @@ int16_t EnforceCoolingSetpointLimits(int16_t CoolingSetpoint, EndpointId endpoin return CoolingSetpoint; } +struct SetpointLimits +{ + bool autoSupported = false; + bool heatSupported = false; + bool coolSupported = false; + bool occupancySupported = false; + + int16_t absMinHeatSetpointLimit; + int16_t absMaxHeatSetpointLimit; + int16_t minHeatSetpointLimit; + int16_t maxHeatSetpointLimit; + int16_t absMinCoolSetpointLimit; + int16_t absMaxCoolSetpointLimit; + int16_t minCoolSetpointLimit; + int16_t maxCoolSetpointLimit; + int16_t deadBand = 0; + int16_t occupiedCoolingSetpoint; + int16_t occupiedHeatingSetpoint; + int16_t unoccupiedCoolingSetpoint; + int16_t unoccupiedHeatingSetpoint; +}; + +/** + * @brief Reads all the attributes for enforcing setpoint limits + * + * @param endpoint The endpoint for the server whose limits are being enforced + * @param setpointLimits The SetpointLimits to populate + * @return Success if the limits were read completely, otherwise an error code + */ +Status GetSetpointLimits(EndpointId endpoint, SetpointLimits & setpointLimits) +{ + uint32_t flags; + if (FeatureMap::Get(endpoint, &flags) != Status::Success) + { + ChipLogError(Zcl, "GetSetpointLimits: could not get feature flags"); + flags = FEATURE_MAP_DEFAULT; + } + + auto featureMap = BitMask(flags); + setpointLimits.autoSupported = featureMap.Has(Feature::kAutoMode); + setpointLimits.heatSupported = featureMap.Has(Feature::kHeating); + setpointLimits.coolSupported = featureMap.Has(Feature::kCooling); + setpointLimits.occupancySupported = featureMap.Has(Feature::kOccupancy); + + if (setpointLimits.autoSupported) + { + int8_t deadBand; + if (MinSetpointDeadBand::Get(endpoint, &deadBand) != Status::Success) + { + deadBand = kDefaultDeadBand; + } + setpointLimits.deadBand = static_cast(deadBand * 10); + } + + if (AbsMinCoolSetpointLimit::Get(endpoint, &setpointLimits.absMinCoolSetpointLimit) != Status::Success) + setpointLimits.absMinCoolSetpointLimit = kDefaultAbsMinCoolSetpointLimit; + + if (AbsMaxCoolSetpointLimit::Get(endpoint, &setpointLimits.absMaxCoolSetpointLimit) != Status::Success) + setpointLimits.absMaxCoolSetpointLimit = kDefaultAbsMaxCoolSetpointLimit; + + if (MinCoolSetpointLimit::Get(endpoint, &setpointLimits.minCoolSetpointLimit) != Status::Success) + setpointLimits.minCoolSetpointLimit = setpointLimits.absMinCoolSetpointLimit; + + if (MaxCoolSetpointLimit::Get(endpoint, &setpointLimits.maxCoolSetpointLimit) != Status::Success) + setpointLimits.maxCoolSetpointLimit = setpointLimits.absMaxCoolSetpointLimit; + + if (AbsMinHeatSetpointLimit::Get(endpoint, &setpointLimits.absMinHeatSetpointLimit) != Status::Success) + setpointLimits.absMinHeatSetpointLimit = kDefaultAbsMinHeatSetpointLimit; + + if (AbsMaxHeatSetpointLimit::Get(endpoint, &setpointLimits.absMaxHeatSetpointLimit) != Status::Success) + setpointLimits.absMaxHeatSetpointLimit = kDefaultAbsMaxHeatSetpointLimit; + + if (MinHeatSetpointLimit::Get(endpoint, &setpointLimits.minHeatSetpointLimit) != Status::Success) + setpointLimits.minHeatSetpointLimit = setpointLimits.absMinHeatSetpointLimit; + + if (MaxHeatSetpointLimit::Get(endpoint, &setpointLimits.maxHeatSetpointLimit) != Status::Success) + setpointLimits.maxHeatSetpointLimit = setpointLimits.absMaxHeatSetpointLimit; + + if (setpointLimits.coolSupported) + { + if (OccupiedCoolingSetpoint::Get(endpoint, &setpointLimits.occupiedCoolingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Occupied Cooling Setpoint"); + return Status::Failure; + } + } + + if (setpointLimits.heatSupported) + { + if (OccupiedHeatingSetpoint::Get(endpoint, &setpointLimits.occupiedHeatingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Occupied Heating Setpoint"); + return Status::Failure; + } + } + + if (setpointLimits.coolSupported && setpointLimits.occupancySupported) + { + if (UnoccupiedCoolingSetpoint::Get(endpoint, &setpointLimits.unoccupiedCoolingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Unoccupied Cooling Setpoint"); + return Status::Failure; + } + } + + if (setpointLimits.heatSupported && setpointLimits.occupancySupported) + { + if (UnoccupiedHeatingSetpoint::Get(endpoint, &setpointLimits.unoccupiedHeatingSetpoint) != Status::Success) + { + // We're substituting the failure code here for backwards-compatibility reasons + ChipLogError(Zcl, "Error: Can not read Unoccupied Heating Setpoint"); + return Status::Failure; + } + } + return Status::Success; +} + +/** + * @brief Checks to see if it's possible to adjust the heating setpoint to preserve a given deadband + * if the cooling setpoint is changed + * + * @param autoSupported Whether or not the thermostat supports Auto mode + * @param newCoolingSetpoing The desired cooling setpoint + * @param minHeatingSetpoint The minimum allowed heating setpoint + * @param deadband The deadband to preserve + * @return Success if the deadband can be preserved, InvalidValue if it cannot + */ +Status CheckHeatingSetpointDeadband(bool autoSupported, int16_t newCoolingSetpoint, int16_t minHeatingSetpoint, int16_t deadband) +{ + if (!autoSupported) + { + return Status::Success; + } + int16_t maxValidHeatingSetpoint = static_cast(newCoolingSetpoint - deadband); + if (maxValidHeatingSetpoint < minHeatingSetpoint) + { + // If we need to adjust the heating setpoint to preserve the deadband, it will go below the min heat setpoint + return Status::InvalidValue; + } + // It's possible to adjust the heating setpoint, if needed + return Status::Success; +} + +/** + * @brief Checks to see if it's possible to adjust the cooling setpoint to preserve a given deadband + * if the heating setpoint is changed + * + * @param autoSupported Whether or not the thermostat supports Auto mode + * @param newHeatingSetpoint The desired heating setpoint + * @param maxCoolingSetpoint The maximum allowed cooling setpoint + * @param deadband The deadband to preserve + * @return Success if the deadband can be preserved, InvalidValue if it cannot + */ +Status CheckCoolingSetpointDeadband(bool autoSupported, int16_t newHeatingSetpoint, int16_t maxCoolingSetpoint, int16_t deadband) +{ + if (!autoSupported) + { + return Status::Success; + } + int16_t minValidCoolingSetpoint = static_cast(newHeatingSetpoint + deadband); + if (minValidCoolingSetpoint > maxCoolingSetpoint) + { + // If we need to adjust the cooling setpoint to preserve the deadband, it will go above the max cool setpoint + return Status::InvalidValue; + } + // It's possible to adjust the cooling setpoint, if needed + return Status::Success; +} + +typedef Status (*SetpointSetter)(EndpointId endpoint, int16_t value); + +/** + * @brief Attempts to ensure that a change to the heating setpoint maintains the deadband with the cooling setpoint + * by adjusting the cooling setpoint + * + * @param endpoint The endpoint on which the heating setpoint has been changed + * @param currentCoolingSetpoint The current cooling setpoint + * @param newHeatingSetpoint The newly adjusted heating setpoint + * @param maxCoolingSetpoint The maximum allowed cooling setpoint + * @param deadband The deadband to preserve + * @param setter A function for setting the cooling setpoint + */ +void EnsureCoolingSetpointDeadband(EndpointId endpoint, int16_t currentCoolingSetpoint, int16_t newHeatingSetpoint, + int16_t maxCoolingSetpoint, int16_t deadband, SetpointSetter setter) +{ + int16_t minValidCoolingSetpoint = static_cast(newHeatingSetpoint + deadband); + if (currentCoolingSetpoint >= minValidCoolingSetpoint) + { + // The current cooling setpoint doesn't violate the deadband + return; + } + if (minValidCoolingSetpoint > maxCoolingSetpoint) + { + // Adjusting the cool setpoint to preserve the deadband would violate the max cool setpoint + // This should have been caught in CheckCoolingSetpointDeadband, so log and exit + ChipLogError(Zcl, "Failed ensuring cooling setpoint deadband"); + return; + } + // Adjust the cool setpoint to preserve deadband + auto status = setter(endpoint, minValidCoolingSetpoint); + if (status != Status::Success) + { + ChipLogError(Zcl, "Error: EnsureCoolingSetpointDeadband failed!"); + } +} + +/** + * @brief Attempts to ensure that a change to the cooling setpoint maintains the deadband with the heating setpoint + * by adjusting the heating setpoint + * + * @param endpoint The endpoint on which the cooling setpoint has been changed + * @param currentHeatingSetpointThe current heating setpoint + * @param newCoolingSetpoint The newly adjusted cooling setpoint + * @param minHeatingSetpoint The minimum allowed cooling setpoint + * @param deadband The deadband to preserve + * @param setter A function for setting the heating setpoint + */ +void EnsureHeatingSetpointDeadband(EndpointId endpoint, int16_t currentHeatingSetpoint, int16_t newCoolingSetpoint, + int16_t minHeatingSetpoint, int16_t deadband, SetpointSetter setter) +{ + int16_t maxValidHeatingSetpoint = static_cast(newCoolingSetpoint - deadband); + if (currentHeatingSetpoint <= maxValidHeatingSetpoint) + { + // The current heating setpoint doesn't violate the deadband + return; + } + if (maxValidHeatingSetpoint < minHeatingSetpoint) + { + // Adjusting the heating setpoint to preserve the deadband would violate the min heating setpoint + // This should have been caught in CheckHeatingSetpointDeadband, so log and exit + ChipLogError(Zcl, "Failed ensuring heating setpoint deadband"); + return; + } + // Adjust the heating setpoint to preserve deadband + auto status = setter(endpoint, maxValidHeatingSetpoint); + if (status != Status::Success) + { + ChipLogError(Zcl, "Error: EnsureHeatingSetpointDeadband failed!"); + } +} + +/** + * @brief For thermostats that support auto, shift setpoints to maintain the current deadband + * Note: this assumes that the shift is possible; setpoint changes which prevent the deadband + * from being maintained due to the min/max limits for setpoints should be rejected by + * MatterThermostatClusterServerPreAttributeChangedCallback + * + * @param attributePath + */ +void EnsureDeadband(const ConcreteAttributePath & attributePath) +{ + auto endpoint = attributePath.mEndpointId; + SetpointLimits setpointLimits; + auto status = GetSetpointLimits(endpoint, setpointLimits); + if (status != Status::Success) + { + return; + } + if (!setpointLimits.autoSupported) + { + return; + } + switch (attributePath.mAttributeId) + { + case OccupiedHeatingSetpoint::Id: + EnsureCoolingSetpointDeadband(endpoint, setpointLimits.occupiedCoolingSetpoint, setpointLimits.occupiedHeatingSetpoint, + setpointLimits.maxCoolSetpointLimit, setpointLimits.deadBand, OccupiedCoolingSetpoint::Set); + break; + case OccupiedCoolingSetpoint::Id: + EnsureHeatingSetpointDeadband(endpoint, setpointLimits.occupiedHeatingSetpoint, setpointLimits.occupiedCoolingSetpoint, + setpointLimits.minHeatSetpointLimit, setpointLimits.deadBand, OccupiedHeatingSetpoint::Set); + break; + case UnoccupiedHeatingSetpoint::Id: + EnsureCoolingSetpointDeadband(endpoint, setpointLimits.unoccupiedCoolingSetpoint, setpointLimits.unoccupiedHeatingSetpoint, + setpointLimits.maxCoolSetpointLimit, setpointLimits.deadBand, UnoccupiedCoolingSetpoint::Set); + break; + case UnoccupiedCoolingSetpoint::Id: + EnsureHeatingSetpointDeadband(endpoint, setpointLimits.unoccupiedHeatingSetpoint, setpointLimits.unoccupiedCoolingSetpoint, + setpointLimits.minHeatSetpointLimit, setpointLimits.deadBand, UnoccupiedHeatingSetpoint::Set); + break; + } +} + Delegate * GetDelegate(EndpointId endpoint) { uint16_t ep = @@ -477,14 +763,9 @@ void MatterThermostatClusterServerAttributeChangedCallback(const ConcreteAttribu return; } - auto featureMap = BitMask(flags); - if (!featureMap.Has(Feature::kPresets)) - { - // This server does not support presets, so nothing to do - return; - } - - bool occupied = true; + auto featureMap = BitMask(flags); + bool supportsPresets = featureMap.Has(Feature::kPresets); + bool occupied = true; if (featureMap.Has(Feature::kOccupancy)) { BitMask occupancy; @@ -499,19 +780,20 @@ void MatterThermostatClusterServerAttributeChangedCallback(const ConcreteAttribu { case OccupiedHeatingSetpoint::Id: case OccupiedCoolingSetpoint::Id: - clearActivePreset = occupied; + clearActivePreset = supportsPresets && occupied; + EnsureDeadband(attributePath); break; case UnoccupiedHeatingSetpoint::Id: case UnoccupiedCoolingSetpoint::Id: - clearActivePreset = !occupied; + clearActivePreset = supportsPresets && !occupied; + EnsureDeadband(attributePath); break; } - if (!clearActivePreset) + if (clearActivePreset) { - return; + ChipLogProgress(Zcl, "Setting active preset to null"); + gThermostatAttrAccess.SetActivePreset(attributePath.mEndpointId, std::nullopt); } - ChipLogProgress(Zcl, "Setting active preset to null"); - gThermostatAttrAccess.SetActivePreset(attributePath.mEndpointId, std::nullopt); } } // namespace Thermostat @@ -535,15 +817,15 @@ void emberAfThermostatClusterServerInitCallback(chip::EndpointId endpoint) // or should this just be the responsibility of the thermostat application? } -Protocols::InteractionModel::Status -MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttributePath & attributePath, - EmberAfAttributeType attributeType, uint16_t size, uint8_t * value) +Status MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttributePath & attributePath, + EmberAfAttributeType attributeType, uint16_t size, uint8_t * value) { EndpointId endpoint = attributePath.mEndpointId; int16_t requested; // Limits will be needed for all checks // so we just get them all now + // TODO: use GetSetpointLimits to fetch this information int16_t AbsMinHeatSetpointLimit; int16_t AbsMaxHeatSetpointLimit; int16_t MinHeatSetpointLimit; @@ -649,12 +931,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinHeatSetpointLimit || requested < MinHeatSetpointLimit || requested > AbsMaxHeatSetpointLimit || requested > MaxHeatSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested > OccupiedCoolingSetpoint - DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckCoolingSetpointDeadband(AutoSupported, requested, std::min(MaxCoolSetpointLimit, AbsMaxCoolSetpointLimit), + DeadBandTemp); } case OccupiedCoolingSetpoint::Id: { @@ -664,12 +942,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinCoolSetpointLimit || requested < MinCoolSetpointLimit || requested > AbsMaxCoolSetpointLimit || requested > MaxCoolSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested < OccupiedHeatingSetpoint + DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckHeatingSetpointDeadband(AutoSupported, requested, std::max(MinHeatSetpointLimit, AbsMinHeatSetpointLimit), + DeadBandTemp); } case UnoccupiedHeatingSetpoint::Id: { @@ -679,12 +953,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinHeatSetpointLimit || requested < MinHeatSetpointLimit || requested > AbsMaxHeatSetpointLimit || requested > MaxHeatSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested > UnoccupiedCoolingSetpoint - DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckCoolingSetpointDeadband(AutoSupported, requested, std::min(MaxCoolSetpointLimit, AbsMaxCoolSetpointLimit), + DeadBandTemp); } case UnoccupiedCoolingSetpoint::Id: { requested = static_cast(chip::Encoding::LittleEndian::Get16(value)); @@ -693,12 +963,8 @@ MatterThermostatClusterServerPreAttributeChangedCallback(const app::ConcreteAttr if (requested < AbsMinCoolSetpointLimit || requested < MinCoolSetpointLimit || requested > AbsMaxCoolSetpointLimit || requested > MaxCoolSetpointLimit) return Status::InvalidValue; - if (AutoSupported) - { - if (requested < UnoccupiedHeatingSetpoint + DeadBandTemp) - return Status::InvalidValue; - } - return Status::Success; + return CheckHeatingSetpointDeadband(AutoSupported, requested, std::max(MinHeatSetpointLimit, AbsMinHeatSetpointLimit), + DeadBandTemp); } case MinHeatSetpointLimit::Id: { From 73ff58ff14c91c590c679a40c9570e434dbdd88f Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 11:19:38 -0800 Subject: [PATCH 008/219] [Fabric-Sync] Use Meyers' Singleton pattern for BridgedDeviceManager and DeviceManager (#36491) --- .../fabric-sync/admin/BridgeSubscription.cpp | 4 +-- .../fabric-sync/admin/CommissionerControl.cpp | 2 +- examples/fabric-sync/admin/DeviceManager.cpp | 3 --- examples/fabric-sync/admin/DeviceManager.h | 25 +++++-------------- .../admin/DeviceSynchronization.cpp | 8 +++--- examples/fabric-sync/admin/FabricAdmin.cpp | 4 +-- .../bridge/include/BridgedDeviceManager.h | 21 +++++----------- examples/fabric-sync/bridge/src/Bridge.cpp | 4 +-- .../src/BridgedAdministratorCommissioning.cpp | 2 +- .../src/BridgedDeviceBasicInformationImpl.cpp | 4 +-- .../bridge/src/BridgedDeviceManager.cpp | 3 --- .../fabric-sync/bridge/src/FabricBridge.cpp | 12 ++++----- .../fabric-sync/shell/AddBridgeCommand.cpp | 12 ++++----- .../fabric-sync/shell/AddDeviceCommand.cpp | 6 ++--- .../fabric-sync/shell/RemoveBridgeCommand.cpp | 6 ++--- .../fabric-sync/shell/RemoveDeviceCommand.cpp | 4 +-- 16 files changed, 46 insertions(+), 74 deletions(-) diff --git a/examples/fabric-sync/admin/BridgeSubscription.cpp b/examples/fabric-sync/admin/BridgeSubscription.cpp index e7052d7df0..1df9371ff7 100644 --- a/examples/fabric-sync/admin/BridgeSubscription.cpp +++ b/examples/fabric-sync/admin/BridgeSubscription.cpp @@ -80,7 +80,7 @@ void BridgeSubscription::OnAttributeData(const ConcreteDataAttributePath & path, return; } - DeviceMgr().HandleAttributeData(path, *data); + DeviceManager::Instance().HandleAttributeData(path, *data); } void BridgeSubscription::OnEventData(const app::EventHeader & eventHeader, TLV::TLVReader * data, const app::StatusIB * status) @@ -101,7 +101,7 @@ void BridgeSubscription::OnEventData(const app::EventHeader & eventHeader, TLV:: return; } - DeviceMgr().HandleEventData(eventHeader, *data); + DeviceManager::Instance().HandleEventData(eventHeader, *data); } void BridgeSubscription::OnError(CHIP_ERROR error) diff --git a/examples/fabric-sync/admin/CommissionerControl.cpp b/examples/fabric-sync/admin/CommissionerControl.cpp index 45c7bc02da..a0c24eb956 100644 --- a/examples/fabric-sync/admin/CommissionerControl.cpp +++ b/examples/fabric-sync/admin/CommissionerControl.cpp @@ -84,7 +84,7 @@ void CommissionerControl::OnResponse(app::CommandSender * client, const app::Con if (data != nullptr) { - DeviceMgr().HandleCommandResponse(path, *data); + DeviceManager::Instance().HandleCommandResponse(path, *data); } } diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 9848d2f68d..6dfdad1213 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -36,9 +36,6 @@ constexpr EndpointId kAggregatorEndpointId = 1; } // namespace -// Define the static member -DeviceManager DeviceManager::sInstance; - LinuxCommissionableDataProvider sCommissionableDataProvider; void DeviceManager::Init() diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index b92154c1e6..e114a62748 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -54,6 +54,12 @@ class DeviceManager public: DeviceManager() = default; + static DeviceManager & Instance() + { + static DeviceManager instance; + return instance; + } + void Init(); chip::NodeId GetNextAvailableNodeId(); @@ -170,8 +176,6 @@ class DeviceManager SyncedDevice * FindDeviceByNode(chip::NodeId nodeId); private: - friend DeviceManager & DeviceMgr(); - void RequestCommissioningApproval(); void HandleReadSupportedDeviceCategories(chip::TLV::TLVReader & data); @@ -184,8 +188,6 @@ class DeviceManager void HandleReverseOpenCommissioningWindow(chip::TLV::TLVReader & data); - static DeviceManager sInstance; - chip::NodeId mLastUsedNodeId = 0; // The Node ID of the remote bridge used for Fabric-Sync @@ -201,19 +203,4 @@ class DeviceManager FabricSyncGetter mFabricSyncGetter; }; -/** - * Returns the public interface of the DeviceManager singleton object. - * - * Applications should use this to access features of the DeviceManager - * object. - */ -inline DeviceManager & DeviceMgr() -{ - if (!DeviceManager::sInstance.mInitialized) - { - DeviceManager::sInstance.Init(); - } - return DeviceManager::sInstance; -} - } // namespace admin diff --git a/examples/fabric-sync/admin/DeviceSynchronization.cpp b/examples/fabric-sync/admin/DeviceSynchronization.cpp index 2f36eb9cb0..05a4fa9db8 100644 --- a/examples/fabric-sync/admin/DeviceSynchronization.cpp +++ b/examples/fabric-sync/admin/DeviceSynchronization.cpp @@ -148,7 +148,7 @@ void DeviceSynchronizer::OnDone(app::ReadClient * apReadClient) { ChipLogProgress(NotSpecified, "Synchronization complete for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); - if (mState == State::ReceivedResponse && !DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + if (mState == State::ReceivedResponse && !DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { GetUniqueId(); if (mState == State::GettingUid) @@ -229,15 +229,15 @@ void DeviceSynchronizer::GetUniqueId() // If we have a UniqueId we can return leaving state in ReceivedResponse. VerifyOrReturn(!mCurrentDeviceData.uniqueId.has_value(), ChipLogDetail(NotSpecified, "We already have UniqueId")); - auto * device = DeviceMgr().FindDeviceByNode(mNodeId); + auto * device = DeviceManager::Instance().FindDeviceByNode(mNodeId); // If there is no associated remote Fabric Sync Aggregator there is no other place for us to try // getting the UniqueId from and can return leaving the state in ReceivedResponse. VerifyOrReturn(device, ChipLogDetail(NotSpecified, "No remote Fabric Sync Aggregator to get UniqueId from")); // Because device is not-null we expect IsFabricSyncReady to be true. IsFabricSyncReady indicates we have a // connection to the remote Fabric Sync Aggregator. - VerifyOrDie(DeviceMgr().IsFabricSyncReady()); - auto remoteBridgeNodeId = DeviceMgr().GetRemoteBridgeNodeId(); + VerifyOrDie(DeviceManager::Instance().IsFabricSyncReady()); + auto remoteBridgeNodeId = DeviceManager::Instance().GetRemoteBridgeNodeId(); EndpointId remoteEndpointIdOfInterest = device->GetEndpointId(); ChipLogDetail(NotSpecified, "Attempting to get UniqueId from remote Fabric Sync Aggregator"); diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index a012ac9d8c..65b5a5a8e8 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -65,13 +65,13 @@ FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParam if (err == CHIP_NO_ERROR) { - NodeId nodeId = DeviceMgr().GetNextAvailableNodeId(); + NodeId nodeId = DeviceManager::Instance().GetNextAvailableNodeId(); // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); - DeviceMgr().PairRemoteDevice(nodeId, code.c_str()); + DeviceManager::Instance().PairRemoteDevice(nodeId, code.c_str()); } else { diff --git a/examples/fabric-sync/bridge/include/BridgedDeviceManager.h b/examples/fabric-sync/bridge/include/BridgedDeviceManager.h index be6c6a41db..67efe74add 100644 --- a/examples/fabric-sync/bridge/include/BridgedDeviceManager.h +++ b/examples/fabric-sync/bridge/include/BridgedDeviceManager.h @@ -30,6 +30,12 @@ class BridgedDeviceManager public: BridgedDeviceManager() = default; + static BridgedDeviceManager & Instance() + { + static BridgedDeviceManager instance; + return instance; + } + /** * @brief Initializes the BridgedDeviceManager. * @@ -111,29 +117,14 @@ class BridgedDeviceManager BridgedDevice * GetDeviceByUniqueId(const std::string & id); private: - friend BridgedDeviceManager & BridgeDeviceMgr(); - /** * Creates a new unique ID that is not used by any other mDevice */ std::string GenerateUniqueId(); - static BridgedDeviceManager sInstance; - chip::EndpointId mCurrentEndpointId; chip::EndpointId mFirstDynamicEndpointId; std::unique_ptr mDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT + 1]; }; -/** - * Returns the public interface of the BridgedDeviceManager singleton object. - * - * Applications should use this to access features of the BridgedDeviceManager - * object. - */ -inline BridgedDeviceManager & BridgeDeviceMgr() -{ - return BridgedDeviceManager::sInstance; -} - } // namespace bridge diff --git a/examples/fabric-sync/bridge/src/Bridge.cpp b/examples/fabric-sync/bridge/src/Bridge.cpp index 02bda529ca..3d0a4af56f 100644 --- a/examples/fabric-sync/bridge/src/Bridge.cpp +++ b/examples/fabric-sync/bridge/src/Bridge.cpp @@ -81,7 +81,7 @@ void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & hand return; } - BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId); + BridgedDevice * device = BridgedDeviceManager::Instance().GetDevice(endpointId); if (device == nullptr || !device->IsIcd()) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::Failure); @@ -125,7 +125,7 @@ CHIP_ERROR BridgeInit(FabricAdminDelegate * delegate) CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gBridgedDeviceInformationCommandHandler); AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes); - BridgeDeviceMgr().Init(); + BridgedDeviceManager::Instance().Init(); FabricBridge::Instance().SetDelegate(delegate); ReturnErrorOnFailure(gBridgedAdministratorCommissioning.Init()); ReturnErrorOnFailure(CommissionerControlInit(delegate)); diff --git a/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp b/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp index 3299df75a9..6cfb5a5caa 100644 --- a/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp +++ b/examples/fabric-sync/bridge/src/BridgedAdministratorCommissioning.cpp @@ -45,7 +45,7 @@ CHIP_ERROR BridgedAdministratorCommissioning::Read(const ConcreteReadAttributePa { VerifyOrDie(aPath.mClusterId == Clusters::AdministratorCommissioning::Id); EndpointId endpointId = aPath.mEndpointId; - BridgedDevice * device = BridgeDeviceMgr().GetDevice(endpointId); + BridgedDevice * device = BridgedDeviceManager::Instance().GetDevice(endpointId); if (!device) { diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp index d021671c8b..3a03d8f84a 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceBasicInformationImpl.cpp @@ -36,7 +36,7 @@ CHIP_ERROR BridgedDeviceBasicInformationImpl::Read(const ConcreteReadAttributePa // Registration is done for the bridged device basic information only VerifyOrDie(path.mClusterId == app::Clusters::BridgedDeviceBasicInformation::Id); - BridgedDevice * dev = BridgeDeviceMgr().GetDevice(path.mEndpointId); + BridgedDevice * dev = BridgedDeviceManager::Instance().GetDevice(path.mEndpointId); VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); switch (path.mAttributeId) @@ -93,7 +93,7 @@ CHIP_ERROR BridgedDeviceBasicInformationImpl::Write(const ConcreteDataAttributeP { VerifyOrDie(path.mClusterId == app::Clusters::BridgedDeviceBasicInformation::Id); - BridgedDevice * dev = BridgeDeviceMgr().GetDevice(path.mEndpointId); + BridgedDevice * dev = BridgedDeviceManager::Instance().GetDevice(path.mEndpointId); VerifyOrReturnError(dev != nullptr, CHIP_ERROR_NOT_FOUND); if (!dev->IsReachable()) diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp index 62d423dc9a..0ead453572 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp @@ -175,9 +175,6 @@ const EmberAfDeviceType sBridgedDeviceTypes[] = { { DEVICE_TYPE_BRIDGED_NODE, DE } // namespace -// Define the static member -BridgedDeviceManager BridgedDeviceManager::sInstance; - void BridgedDeviceManager::Init() { mFirstDynamicEndpointId = static_cast( diff --git a/examples/fabric-sync/bridge/src/FabricBridge.cpp b/examples/fabric-sync/bridge/src/FabricBridge.cpp index d1c27d2409..aa856ccf12 100644 --- a/examples/fabric-sync/bridge/src/FabricBridge.cpp +++ b/examples/fabric-sync/bridge/src/FabricBridge.cpp @@ -103,7 +103,7 @@ CHIP_ERROR FabricBridge::AddSynchronizedDevice(const SynchronizedDevice & data) device->SetIcd(data.isIcd.value_or(false)); // Add the device to the bridge manager with a parent endpoint - auto result = BridgeDeviceMgr().AddDeviceEndpoint(std::move(device), /* parentEndpointId= */ 1); + auto result = BridgedDeviceManager::Instance().AddDeviceEndpoint(std::move(device), /* parentEndpointId= */ 1); if (!result.has_value()) { ChipLogError(NotSpecified, "Failed to add device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(), @@ -112,7 +112,7 @@ CHIP_ERROR FabricBridge::AddSynchronizedDevice(const SynchronizedDevice & data) } // Retrieve and verify the added device by ScopedNodeId - BridgedDevice * addedDevice = BridgeDeviceMgr().GetDeviceByScopedNodeId(data.id); + BridgedDevice * addedDevice = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(data.id); VerifyOrDie(addedDevice); ChipLogProgress(NotSpecified, "Added device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(), @@ -137,7 +137,7 @@ CHIP_ERROR FabricBridge::RemoveSynchronizedDevice(ScopedNodeId scopedNodeId) ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); - auto removedIdx = BridgeDeviceMgr().RemoveDeviceByScopedNodeId(scopedNodeId); + auto removedIdx = BridgedDeviceManager::Instance().RemoveDeviceByScopedNodeId(scopedNodeId); if (!removedIdx.has_value()) { ChipLogError(NotSpecified, "Failed to remove device with Id=[%d:0x" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), @@ -153,7 +153,7 @@ CHIP_ERROR FabricBridge::ActiveChanged(ScopedNodeId scopedNodeId, uint32_t promi ChipLogProgress(NotSpecified, "Received ActiveChanged: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); - auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId); + auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(scopedNodeId); if (device == nullptr) { ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", @@ -170,7 +170,7 @@ CHIP_ERROR FabricBridge::AdminCommissioningAttributeChanged(const AdministratorC ChipLogProgress(NotSpecified, "Received CADMIN attribute change: Id=[%d:" ChipLogFormatX64 "]", data.id.GetFabricIndex(), ChipLogValueX64(data.id.GetNodeId())); - auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(data.id); + auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(data.id); if (device == nullptr) { ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", @@ -207,7 +207,7 @@ CHIP_ERROR FabricBridge::DeviceReachableChanged(ScopedNodeId scopedNodeId, bool ChipLogProgress(NotSpecified, "Received device reachable changed: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); - auto * device = BridgeDeviceMgr().GetDeviceByScopedNodeId(scopedNodeId); + auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(scopedNodeId); if (device == nullptr) { ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]", diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index 4b70998dcc..e6b9dd0603 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -48,13 +48,13 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) if (err == CHIP_NO_ERROR) { - admin::DeviceMgr().SetRemoteBridgeNodeId(mBridgeNodeId); + admin::DeviceManager::Instance().SetRemoteBridgeNodeId(mBridgeNodeId); ChipLogProgress(NotSpecified, "Successfully paired bridge device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mBridgeNodeId)); - admin::DeviceMgr().UpdateLastUsedNodeId(mBridgeNodeId); - admin::DeviceMgr().SubscribeRemoteFabricBridge(); + admin::DeviceManager::Instance().UpdateLastUsedNodeId(mBridgeNodeId); + admin::DeviceManager::Instance().SubscribeRemoteFabricBridge(); // After successful commissioning of the Commissionee, initiate Reverse Commissioning // via the Commissioner Control Cluster. However, we must first verify that the @@ -62,7 +62,7 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) // // Note: The Fabric-Admin MUST NOT send the RequestCommissioningApproval command // if the remote Fabric-Bridge lacks Fabric Synchronization support. - DeviceLayer::SystemLayer().ScheduleLambda([]() { admin::DeviceMgr().ReadSupportedDeviceCategories(); }); + DeviceLayer::SystemLayer().ScheduleLambda([]() { admin::DeviceManager::Instance().ReadSupportedDeviceCategories(); }); } else { @@ -75,7 +75,7 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR AddBridgeCommand::RunCommand() { - if (admin::DeviceMgr().IsFabricSyncReady()) + if (admin::DeviceManager::Instance().IsFabricSyncReady()) { // print to console fprintf(stderr, "Remote Fabric Bridge has already been configured.\n"); @@ -87,7 +87,7 @@ CHIP_ERROR AddBridgeCommand::RunCommand() ChipLogProgress(NotSpecified, "Running AddBridgeCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); - return admin::DeviceMgr().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::DeviceManager::Instance().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/AddDeviceCommand.cpp b/examples/fabric-sync/shell/AddDeviceCommand.cpp index a85de7695d..a79e4696ca 100644 --- a/examples/fabric-sync/shell/AddDeviceCommand.cpp +++ b/examples/fabric-sync/shell/AddDeviceCommand.cpp @@ -51,7 +51,7 @@ void AddDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { ChipLogProgress(NotSpecified, "Successfully paired device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mNodeId)); - admin::DeviceMgr().UpdateLastUsedNodeId(mNodeId); + admin::DeviceManager::Instance().UpdateLastUsedNodeId(mNodeId); } else { @@ -64,7 +64,7 @@ void AddDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR AddDeviceCommand::RunCommand() { - if (admin::DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + if (admin::DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { // print to console fprintf(stderr, "The specified node ID has been reserved by the Fabric Bridge.\n"); @@ -76,7 +76,7 @@ CHIP_ERROR AddDeviceCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceMgr().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::DeviceManager::Instance().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp index 77bd76be33..9a33b0b11b 100644 --- a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp +++ b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp @@ -35,7 +35,7 @@ void RemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) if (err == CHIP_NO_ERROR) { - admin::DeviceMgr().SetRemoteBridgeNodeId(kUndefinedNodeId); + admin::DeviceManager::Instance().SetRemoteBridgeNodeId(kUndefinedNodeId); // print to console fprintf(stderr, "Successfully removed bridge device: NodeId: " ChipLogFormatX64 "\n", ChipLogValueX64(mBridgeNodeId)); @@ -51,7 +51,7 @@ void RemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR RemoveBridgeCommand::RunCommand() { - NodeId bridgeNodeId = admin::DeviceMgr().GetRemoteBridgeNodeId(); + NodeId bridgeNodeId = admin::DeviceManager::Instance().GetRemoteBridgeNodeId(); if (bridgeNodeId == kUndefinedNodeId) { @@ -66,7 +66,7 @@ CHIP_ERROR RemoveBridgeCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceMgr().UnpairRemoteFabricBridge(); + return admin::DeviceManager::Instance().UnpairRemoteFabricBridge(); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp index 78440f8542..5e316658d5 100644 --- a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp +++ b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp @@ -52,7 +52,7 @@ void RemoveDeviceCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) CHIP_ERROR RemoveDeviceCommand::RunCommand() { - if (admin::DeviceMgr().IsCurrentBridgeDevice(mNodeId)) + if (admin::DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { // print to console fprintf(stderr, "The specified node ID has been reserved by the Fabric Bridge.\n"); @@ -63,7 +63,7 @@ CHIP_ERROR RemoveDeviceCommand::RunCommand() ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: %lu", mNodeId); - return admin::DeviceMgr().UnpairRemoteDevice(mNodeId); + return admin::DeviceManager::Instance().UnpairRemoteDevice(mNodeId); } } // namespace commands From 1bdcb74643ad758a9b71f857ef9660e6d2d89c05 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Thu, 14 Nov 2024 23:49:58 +0100 Subject: [PATCH 009/219] [darwin] Update the NetworkFramework UDP implementation (#36418) * [Network.framework] Add chip_system_config_use_network_framework * [Network.framework] Update src/lib/core/CHIPConfig.h file to enable CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical * [Network.framework] Update src/system/SystemConfig.h file to enable CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS * [Network.Framework] Update src/inet/InetInterface* files with some additional #ifdef for the network framework * [Network.Framework] Update src/inet/IPAddress* files with some additional #ifdef for the network framework * [Network.framework] Update src/inet/InetInterfaceImplDefault.cpp to enable the default implementation * [Network.framework] Update src/system to not use WakeEvent/Signal when using the network framework * [Network.framework] Convert UDPEndPointImplNetworkFramework.cpp to .mm with arc support * [chip-tool] Ensure each commissioner listen onto its own udc port since Network.framework won't allow SO_REUSEPORT * [Matter.framework][darwin-framework-tool] Add chip_system_config_use_network_framework flag support * Apply suggestions from code review --------- Co-authored-by: Boris Zbarsky --- .../chip-tool/commands/common/CHIPCommand.cpp | 5 + examples/darwin-framework-tool/BUILD.gn | 14 +- scripts/build/build_darwin_framework.py | 5 +- .../Framework/chip_xcode_build_connector.sh | 6 + src/inet/BUILD.gn | 9 +- src/inet/IPAddress-StringFuncts.cpp | 8 +- src/inet/IPAddress.h | 9 +- src/inet/InetInterface.cpp | 8 +- src/inet/InetInterface.h | 2 +- src/inet/InetInterfaceImpl.h | 2 +- src/inet/InetInterfaceImplDefault.cpp | 2 +- src/inet/UDPEndPointImplNetworkFramework.cpp | 533 -------------- src/inet/UDPEndPointImplNetworkFramework.h | 8 +- src/inet/UDPEndPointImplNetworkFramework.mm | 655 ++++++++++++++++++ src/inet/inet.gni | 7 + src/lib/core/CHIPConfig.h | 6 +- src/system/BUILD.gn | 2 +- src/system/SystemConfig.h | 2 +- src/system/SystemLayer.h | 8 +- src/system/SystemLayerImplSelect.cpp | 40 +- src/system/SystemLayerImplSelect.h | 2 +- src/system/system.gni | 16 +- 22 files changed, 763 insertions(+), 586 deletions(-) delete mode 100644 src/inet/UDPEndPointImplNetworkFramework.cpp create mode 100644 src/inet/UDPEndPointImplNetworkFramework.mm diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 1c3df517bd..4f14cb855e 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -467,6 +467,11 @@ void CHIPCommand::ShutdownCommissioner(const CommissionerIdentity & key) CHIP_ERROR CHIPCommand::InitializeCommissioner(CommissionerIdentity & identity, chip::FabricId fabricId) { std::unique_ptr commissioner = std::make_unique(); +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY + VerifyOrReturnError(chip::CanCastTo(CHIP_UDC_PORT + fabricId), CHIP_ERROR_INVALID_ARGUMENT); + uint16_t udcListenPort = static_cast(CHIP_UDC_PORT + fabricId); + commissioner->SetUdcListenPort(udcListenPort); +#endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY chip::Controller::SetupParams commissionerParams; ReturnLogErrorOnFailure(mCredIssuerCmds->SetupDeviceAttestation(commissionerParams, sTrustStore, sRevocationDelegate)); diff --git a/examples/darwin-framework-tool/BUILD.gn b/examples/darwin-framework-tool/BUILD.gn index fbe1c4d6f8..257431b242 100644 --- a/examples/darwin-framework-tool/BUILD.gn +++ b/examples/darwin-framework-tool/BUILD.gn @@ -46,6 +46,9 @@ declare_args() { # Enable automatic leak checks before the application exits enable_leak_checking = !is_asan && target_os == "mac" + + # Use Network.framework instead of POSIX sockets + use_network_framework = false } sdk = "macosx" @@ -125,6 +128,12 @@ action("build-darwin-framework") { args += [ "--no-enable-encoding-sentinel-enum-values" ] } + if (defined(use_network_framework) && use_network_framework) { + args += [ "--use-network-framework" ] + } else { + args += [ "--no-use-network-framework" ] + } + output_name = "Matter.framework" outputs = [ "${root_out_dir}/macos_framework_output/Build/Products/${output_sdk_type}/${output_name}", @@ -277,10 +286,7 @@ executable("darwin-framework-tool") { "${root_out_dir}/macos_framework_output/Build/Intermediates.noindex/Matter.build/${output_sdk_type}/Matter.build/out/gen/include", ] - defines = [ - "CHIP_HAVE_CONFIG_H=1", - "CHIP_SYSTEM_CONFIG_USE_SOCKETS=1", - ] + defines = [ "CHIP_HAVE_CONFIG_H=1" ] frameworks += [ "CoreFoundation.framework", diff --git a/scripts/build/build_darwin_framework.py b/scripts/build/build_darwin_framework.py index d2d3665a1b..a048241ff1 100644 --- a/scripts/build/build_darwin_framework.py +++ b/scripts/build/build_darwin_framework.py @@ -91,7 +91,8 @@ def build_darwin_framework(args): 'CHIP_IS_ASAN': args.asan, 'CHIP_IS_BLE': args.ble, 'CHIP_IS_CLANG': args.clang, - 'CHIP_ENABLE_ENCODING_SENTINEL_ENUM_VALUES': args.enable_encoding_sentinel_enum_values + 'CHIP_ENABLE_ENCODING_SENTINEL_ENUM_VALUES': args.enable_encoding_sentinel_enum_values, + 'CHIP_USE_NETWORK_FRAMEWORK': args.use_network_framework } for option in options: command += ["{}={}".format(option, "YES" if options[option] else "NO")] @@ -176,6 +177,8 @@ def build_darwin_framework(args): parser.add_argument('--clang', action=argparse.BooleanOptionalAction) parser.add_argument('--enable-encoding-sentinel-enum-values', action=argparse.BooleanOptionalAction) parser.add_argument('--compdb', action=argparse.BooleanOptionalAction) + parser.add_argument('--use-network-framework', + action=argparse.BooleanOptionalAction) args = parser.parse_args() build_darwin_framework(args) diff --git a/src/darwin/Framework/chip_xcode_build_connector.sh b/src/darwin/Framework/chip_xcode_build_connector.sh index 0c08ab381b..7e8e72d213 100755 --- a/src/darwin/Framework/chip_xcode_build_connector.sh +++ b/src/darwin/Framework/chip_xcode_build_connector.sh @@ -187,6 +187,12 @@ esac ) } +[[ $CHIP_USE_NETWORK_FRAMEWORK == YES ]] && { + args+=( + 'chip_system_config_use_network_framework=true' + ) +} + # search current (or $2) and its parent directories until # a name match is found, which is output on stdout find_in_ancestors() { diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn index e30d417ffc..ede5d38373 100644 --- a/src/inet/BUILD.gn +++ b/src/inet/BUILD.gn @@ -158,11 +158,16 @@ static_library("inet") { "EndpointQueueFilter.h", "UDPEndPoint.cpp", "UDPEndPoint.h", - "UDPEndPointImpl${chip_system_config_inet}.cpp", "UDPEndPointImpl${chip_system_config_inet}.h", "UDPEndPointImpl.h", ] + if (chip_system_config_use_network_framework) { + sources += [ "UDPEndPointImpl${chip_system_config_inet}.mm" ] + } else { + sources += [ "UDPEndPointImpl${chip_system_config_inet}.cpp" ] + } + if (chip_system_config_inet == "Sockets") { # TODO: dependency on this one is not clear as it is only ever # enabled through CMakeLists.txt. Added here for completeness @@ -187,5 +192,7 @@ static_library("inet") { cflags = [ "-Wconversion" ] if (current_os == "nuttx") { cflags -= [ "-Wconversion" ] + } else if (chip_system_config_use_network_framework) { + cflags += [ "-fobjc-arc" ] } } diff --git a/src/inet/IPAddress-StringFuncts.cpp b/src/inet/IPAddress-StringFuncts.cpp index 7022b44a6a..2a7ff008a3 100644 --- a/src/inet/IPAddress-StringFuncts.cpp +++ b/src/inet/IPAddress-StringFuncts.cpp @@ -32,7 +32,7 @@ #include #include -#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK +#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS #include #endif @@ -54,7 +54,7 @@ char * IPAddress::ToString(char * buf, uint32_t bufSize) const ip6_addr_t ip6_addr = ToIPv6(); ip6addr_ntoa_r(&ip6_addr, buf, (int) bufSize); } -#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS +#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK // socklen_t is sometimes signed, sometimes not, so the only safe way to do // this is to promote everything to an unsigned type that's known to be big // enough for everything, then cast back to uint32_t after taking the min. @@ -93,7 +93,7 @@ bool IPAddress::FromString(const char * str, IPAddress & output) ip4_addr_t ipv4Addr; if (!ip4addr_aton(str, &ipv4Addr)) return false; -#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS +#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK struct in_addr ipv4Addr; if (inet_pton(AF_INET, str, &ipv4Addr) < 1) return false; @@ -107,7 +107,7 @@ bool IPAddress::FromString(const char * str, IPAddress & output) ip6_addr_t ipv6Addr; if (!ip6addr_aton(str, &ipv6Addr)) return false; -#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS +#elif CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK struct in6_addr ipv6Addr; if (inet_pton(AF_INET6, str, &ipv6Addr) < 1) return false; diff --git a/src/inet/IPAddress.h b/src/inet/IPAddress.h index 2b756ef556..03a40394b5 100644 --- a/src/inet/IPAddress.h +++ b/src/inet/IPAddress.h @@ -56,12 +56,9 @@ #include #endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT -#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK +#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS #include #include -#endif // CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK - -#if CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS #include #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS @@ -110,7 +107,7 @@ enum class IPv6MulticastFlag : uint8_t }; using IPv6MulticastFlags = BitFlags; -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK /** * SockAddr should be used when calling any API that returns (by copying into * it) a sockaddr, because that will need enough storage that it can hold data @@ -139,7 +136,7 @@ union SockAddrWithoutStorage sockaddr_in in; sockaddr_in6 in6; }; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK /** * @brief Internet protocol address diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index af89de8cb9..4595dfef44 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -38,7 +38,7 @@ #include #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #include #include #include @@ -50,7 +50,7 @@ #include #include #include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#endif // (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF #include @@ -434,7 +434,7 @@ CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS CHIP_ERROR InterfaceId::GetInterfaceName(char * nameBuf, size_t nameBufSize) const { @@ -788,7 +788,7 @@ CHIP_ERROR InterfaceId::GetLinkLocalAddr(IPAddress * llAddr) const return (found) ? CHIP_NO_ERROR : INET_ERROR_ADDRESS_NOT_FOUND; } -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#endif // (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF diff --git a/src/inet/InetInterface.h b/src/inet/InetInterface.h index 9603ba80c3..82f3797a8d 100644 --- a/src/inet/InetInterface.h +++ b/src/inet/InetInterface.h @@ -85,7 +85,7 @@ class InterfaceId static constexpr size_t kMaxIfNameLength = 13; // Names are formatted as %c%c%d #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS using PlatformType = unsigned int; static constexpr size_t kMaxIfNameLength = IF_NAMESIZE; #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS diff --git a/src/inet/InetInterfaceImpl.h b/src/inet/InetInterfaceImpl.h index 4d310c998c..00c29cff15 100644 --- a/src/inet/InetInterfaceImpl.h +++ b/src/inet/InetInterfaceImpl.h @@ -19,7 +19,7 @@ #include -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #include namespace chip { diff --git a/src/inet/InetInterfaceImplDefault.cpp b/src/inet/InetInterfaceImplDefault.cpp index 461cbe1b0a..91eafed800 100644 --- a/src/inet/InetInterfaceImplDefault.cpp +++ b/src/inet/InetInterfaceImplDefault.cpp @@ -16,7 +16,7 @@ */ #include -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS #include namespace chip { namespace Inet { diff --git a/src/inet/UDPEndPointImplNetworkFramework.cpp b/src/inet/UDPEndPointImplNetworkFramework.cpp deleted file mode 100644 index 35f6d135a0..0000000000 --- a/src/inet/UDPEndPointImplNetworkFramework.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/* - * - * Copyright (c) 2020-2021 Project CHIP Authors - * Copyright (c) 2018 Google LLC. - * Copyright (c) 2013-2018 Nest Labs, Inc. - * - * 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. - */ - -/** - * This file implements Inet::UDPEndPoint using Network Framework. - */ - -#define __APPLE_USE_RFC_3542 -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define INET_PORTSTRLEN 6 - -namespace chip { -namespace Inet { - -CHIP_ERROR UDPEndPointImplNetworkFramework::BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, - InterfaceId intfId) -{ - nw_parameters_configure_protocol_block_t configure_tls; - nw_parameters_t parameters; - - if (intfId.IsPresent()) - { - return CHIP_ERROR_NOT_IMPLEMENTED; - } - - configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL; - parameters = nw_parameters_create_secure_udp(configure_tls, NW_PARAMETERS_DEFAULT_CONFIGURATION); - VerifyOrReturnError(parameters != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - ReturnErrorOnFailure(ConfigureProtocol(addressType, parameters)); - - nw_endpoint_t endpoint = nullptr; - CHIP_ERROR res = GetEndPoint(endpoint, addressType, address, port); - nw_parameters_set_local_endpoint(parameters, endpoint); - nw_release(endpoint); - ReturnErrorOnFailure(res); - - mDispatchQueue = dispatch_queue_create("inet_dispatch_global", DISPATCH_QUEUE_CONCURRENT); - VerifyOrReturnError(mDispatchQueue != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mDispatchQueue); - - mConnectionSemaphore = dispatch_semaphore_create(0); - VerifyOrReturnError(mConnectionSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mConnectionSemaphore); - - mSendSemaphore = dispatch_semaphore_create(0); - VerifyOrReturnError(mSendSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mSendSemaphore); - - mAddrType = addressType; - mConnection = nullptr; - mParameters = parameters; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::BindInterfaceImpl(IPAddressType addrType, InterfaceId intfId) -{ - return INET_ERROR_UNKNOWN_INTERFACE; -} - -InterfaceId UDPEndPointImplNetworkFramework::GetBoundInterface() const -{ - return InterfaceId::Null(); -} - -uint16_t UDPEndPointImplNetworkFramework::GetBoundPort() const -{ - nw_endpoint_t endpoint = nw_parameters_copy_local_endpoint(mParameters); - return nw_endpoint_get_port(endpoint); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ListenImpl() -{ - return StartListener(); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::SendMsgImpl(const IPPacketInfo * pktInfo, System::PacketBufferHandle && msg) -{ - dispatch_data_t content; - - // Ensure the destination address type is compatible with the endpoint address type. - VerifyOrReturnError(mAddrType == pktInfo->DestAddress.Type(), CHIP_ERROR_INVALID_ARGUMENT); - - // For now the entire message must fit within a single buffer. - VerifyOrReturnError(msg->Next() == nullptr, CHIP_ERROR_MESSAGE_TOO_LONG); - - ReturnErrorOnFailure(GetConnection(pktInfo)); - - // Send a message, and wait for it to be dispatched. - content = dispatch_data_create(msg->Start(), msg->DataLength(), mDispatchQueue, DISPATCH_DATA_DESTRUCTOR_DEFAULT); - - // If there is a current message pending and the state of the network connection change (e.g switch to a - // different network) the connection will enter a nw_connection_state_failed state and the completion handler - // will never be called. In such cases a signal is sent from the connection state change handler to release - // the semaphore. In this case the CHIP_ERROR will not update with the result of the completion handler. - // To make sure caller knows that sending a message has failed the following code consider there is an error - // _unless_ the completion handler says otherwise. - __block CHIP_ERROR res = CHIP_ERROR_UNEXPECTED_EVENT; - nw_connection_send(mConnection, content, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t error) { - if (error) - { - res = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); - } - else - { - res = CHIP_NO_ERROR; - } - dispatch_semaphore_signal(mSendSemaphore); - }); - dispatch_release(content); - - dispatch_semaphore_wait(mSendSemaphore, DISPATCH_TIME_FOREVER); - - return res; -} - -void UDPEndPointImplNetworkFramework::CloseImpl() -{ - ReleaseAll(); -} - -void UDPEndPointImplNetworkFramework::ReleaseAll() -{ - - OnMessageReceived = nullptr; - OnReceiveError = nullptr; - - ReleaseConnection(); - ReleaseListener(); - - if (mParameters) - { - nw_release(mParameters); - mParameters = nullptr; - } - - if (mDispatchQueue) - { - dispatch_suspend(mDispatchQueue); - dispatch_release(mDispatchQueue); - mDispatchQueue = nullptr; - } - - if (mConnectionSemaphore) - { - dispatch_release(mConnectionSemaphore); - mConnectionSemaphore = nullptr; - } - - if (mListenerQueue) - { - dispatch_suspend(mListenerQueue); - dispatch_release(mListenerQueue); - mListenerQueue = nullptr; - } - - if (mListenerSemaphore) - { - dispatch_release(mListenerSemaphore); - mListenerSemaphore = nullptr; - } - - if (mSendSemaphore) - { - dispatch_release(mSendSemaphore); - mSendSemaphore = nullptr; - } -} - -void UDPEndPointImplNetworkFramework::Free() -{ - Close(); - Release(); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -#if INET_CONFIG_ENABLE_IPV4 -CHIP_ERROR UDPEndPointImplNetworkFramework::IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, - bool join) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} -#endif // INET_CONFIG_ENABLE_IPV4 - -CHIP_ERROR UDPEndPointImplNetworkFramework::IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, - bool join) -{ - return CHIP_ERROR_NOT_IMPLEMENTED; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters) -{ - CHIP_ERROR res = CHIP_NO_ERROR; - - nw_protocol_stack_t protocolStack = nw_parameters_copy_default_protocol_stack(aParameters); - nw_protocol_options_t ipOptions = nw_protocol_stack_copy_internet_protocol(protocolStack); - - switch (aAddressType) - { - - case IPAddressType::kIPv6: - nw_ip_options_set_version(ipOptions, nw_ip_version_6); - break; - -#if INET_CONFIG_ENABLE_IPV4 - case IPAddressType::kIPv4: - nw_ip_options_set_version(ipOptions, nw_ip_version_4); - break; -#endif // INET_CONFIG_ENABLE_IPV4 - - default: - res = INET_ERROR_WRONG_ADDRESS_TYPE; - break; - } - nw_release(ipOptions); - nw_release(protocolStack); - - return res; -} - -void UDPEndPointImplNetworkFramework::GetPacketInfo(const nw_connection_t & aConnection, IPPacketInfo & aPacketInfo) -{ - nw_path_t path = nw_connection_copy_current_path(aConnection); - nw_endpoint_t dest_endpoint = nw_path_copy_effective_local_endpoint(path); - nw_endpoint_t src_endpoint = nw_path_copy_effective_remote_endpoint(path); - - aPacketInfo.Clear(); - aPacketInfo.SrcAddress = IPAddress::FromSockAddr(*nw_endpoint_get_address(src_endpoint)); - aPacketInfo.DestAddress = IPAddress::FromSockAddr(*nw_endpoint_get_address(dest_endpoint)); - aPacketInfo.SrcPort = nw_endpoint_get_port(src_endpoint); - aPacketInfo.DestPort = nw_endpoint_get_port(dest_endpoint); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::GetEndPoint(nw_endpoint_t & aEndPoint, const IPAddressType aAddressType, - const IPAddress & aAddress, uint16_t aPort) -{ - char addrStr[INET6_ADDRSTRLEN]; - char portStr[INET_PORTSTRLEN]; - - // Note: aAddress.ToString will return the IPv6 Any address if the address type is Any, but that's not what - // we want if the locale endpoint is IPv4. - if (aAddressType == IPAddressType::kIPv4 && aAddress.Type() == IPAddressType::kAny) - { - const IPAddress anyAddr = IPAddress(aAddress.ToIPv4()); - anyAddr.ToString(addrStr, sizeof(addrStr)); - } - else - { - aAddress.ToString(addrStr, sizeof(addrStr)); - } - - snprintf(portStr, sizeof(portStr), "%u", aPort); - - aEndPoint = nw_endpoint_create_host(addrStr, portStr); - VerifyOrReturnError(aEndPoint != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - return CHIP_NO_ERROR; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::GetConnection(const IPPacketInfo * aPktInfo) -{ - VerifyOrReturnError(mParameters != nullptr, CHIP_ERROR_INCORRECT_STATE); - - nw_endpoint_t endpoint = nullptr; - nw_connection_t connection = nullptr; - - if (mConnection) - { - nw_path_t path = nw_connection_copy_current_path(mConnection); - nw_endpoint_t remote_endpoint = nw_path_copy_effective_remote_endpoint(path); - const IPAddress remote_address = IPAddress::FromSockAddr(*nw_endpoint_get_address(remote_endpoint)); - const uint16_t remote_port = nw_endpoint_get_port(remote_endpoint); - const bool isDifferentEndPoint = aPktInfo->DestPort != remote_port || aPktInfo->DestAddress != remote_address; - VerifyOrReturnError(isDifferentEndPoint, CHIP_NO_ERROR); - - ReturnErrorOnFailure(ReleaseConnection()); - } - - ReturnErrorOnFailure(GetEndPoint(endpoint, mAddrType, aPktInfo->DestAddress, aPktInfo->DestPort)); - - connection = nw_connection_create(endpoint, mParameters); - nw_release(endpoint); - - VerifyOrReturnError(connection != nullptr, CHIP_ERROR_INCORRECT_STATE); - - return StartConnection(connection); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::StartListener() -{ - __block CHIP_ERROR res = CHIP_NO_ERROR; - nw_listener_t listener; - - VerifyOrReturnError(mListener == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mListenerSemaphore == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mListenerQueue == nullptr, CHIP_ERROR_INCORRECT_STATE); - - listener = nw_listener_create(mParameters); - VerifyOrReturnError(listener != nullptr, CHIP_ERROR_INCORRECT_STATE); - - mListenerSemaphore = dispatch_semaphore_create(0); - VerifyOrReturnError(mListenerSemaphore != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mListenerSemaphore); - - mListenerQueue = dispatch_queue_create("inet_dispatch_listener", DISPATCH_QUEUE_CONCURRENT); - VerifyOrReturnError(mListenerQueue != nullptr, CHIP_ERROR_NO_MEMORY); - dispatch_retain(mListenerQueue); - - nw_listener_set_queue(listener, mListenerQueue); - - nw_listener_set_new_connection_handler(listener, ^(nw_connection_t connection) { - ReleaseConnection(); - StartConnection(connection); - }); - - nw_listener_set_state_changed_handler(listener, ^(nw_listener_state_t state, nw_error_t error) { - switch (state) - { - - case nw_listener_state_invalid: - ChipLogDetail(Inet, "Listener: Invalid"); - res = CHIP_ERROR_INCORRECT_STATE; - nw_listener_cancel(listener); - break; - - case nw_listener_state_waiting: - ChipLogDetail(Inet, "Listener: Waiting"); - break; - - case nw_listener_state_failed: - ChipLogDetail(Inet, "Listener: Failed"); - res = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); - break; - - case nw_listener_state_ready: - ChipLogDetail(Inet, "Listener: Ready"); - res = CHIP_NO_ERROR; - dispatch_semaphore_signal(mListenerSemaphore); - break; - - case nw_listener_state_cancelled: - ChipLogDetail(Inet, "Listener: Cancelled"); - if (res == CHIP_NO_ERROR) - { - res = CHIP_ERROR_CONNECTION_ABORTED; - } - - dispatch_semaphore_signal(mListenerSemaphore); - break; - } - }); - - nw_listener_start(listener); - dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); - ReturnErrorOnFailure(res); - - mListener = listener; - nw_retain(mListener); - return res; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::StartConnection(nw_connection_t & aConnection) -{ - __block CHIP_ERROR res = CHIP_NO_ERROR; - - nw_connection_set_queue(aConnection, mDispatchQueue); - - nw_connection_set_state_changed_handler(aConnection, ^(nw_connection_state_t state, nw_error_t error) { - switch (state) - { - - case nw_connection_state_invalid: - ChipLogDetail(Inet, "Connection: Invalid"); - res = CHIP_ERROR_INCORRECT_STATE; - nw_connection_cancel(aConnection); - break; - - case nw_connection_state_preparing: - ChipLogDetail(Inet, "Connection: Preparing"); - res = CHIP_ERROR_INCORRECT_STATE; - break; - - case nw_connection_state_waiting: - ChipLogDetail(Inet, "Connection: Waiting"); - nw_connection_cancel(aConnection); - break; - - case nw_connection_state_failed: - ChipLogDetail(Inet, "Connection: Failed"); - res = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); - break; - - case nw_connection_state_ready: - ChipLogDetail(Inet, "Connection: Ready"); - res = CHIP_NO_ERROR; - dispatch_semaphore_signal(mConnectionSemaphore); - break; - - case nw_connection_state_cancelled: - ChipLogDetail(Inet, "Connection: Cancelled"); - if (res == CHIP_NO_ERROR) - { - res = CHIP_ERROR_CONNECTION_ABORTED; - } - - dispatch_semaphore_signal(mConnectionSemaphore); - break; - } - }); - - nw_connection_start(aConnection); - dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); - SuccessOrExit(res); - - mConnection = aConnection; - nw_retain(mConnection); - HandleDataReceived(mConnection); - - return res; -} - -void UDPEndPointImplNetworkFramework::HandleDataReceived(const nw_connection_t & aConnection) -{ - nw_connection_receive_completion_t handler = - ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) { - dispatch_block_t schedule_next_receive = ^{ - if (receive_error == nullptr) - { - HandleDataReceived(aConnection); - } - else if (OnReceiveError != nullptr) - { - nw_error_domain_t error_domain = nw_error_get_error_domain(receive_error); - errno = nw_error_get_error_code(receive_error); - if (!(error_domain == nw_error_domain_posix && errno == ECANCELED)) - { - CHIP_ERROR error = CHIP_ERROR_POSIX(errno); - IPPacketInfo packetInfo; - GetPacketInfo(aConnection, packetInfo); - dispatch_async(mDispatchQueue, ^{ - OnReceiveError((UDPEndPoint *) this, error, &packetInfo); - }); - } - } - }; - - if (content != nullptr && OnMessageReceived != nullptr) - { - size_t count = dispatch_data_get_size(content); - System::PacketBufferHandle * packetBuffer = System::PacketBufferHandle::New(count); - dispatch_data_apply(content, ^(dispatch_data_t data, size_t offset, const void * buffer, size_t size) { - memmove(packetBuffer->Start() + offset, buffer, size); - return true; - }); - packetBuffer->SetDataLength(count); - - IPPacketInfo packetInfo; - GetPacketInfo(aConnection, packetInfo); - dispatch_async(mDispatchQueue, ^{ - OnMessageReceived((UDPEndPoint *) this, packetBuffer, &packetInfo); - }); - } - - schedule_next_receive(); - }; - - nw_connection_receive_message(aConnection, handler); -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseListener() -{ - VerifyOrReturnError(mListener, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDispatchQueue, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); - - nw_listener_cancel(mListener); - dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); - nw_release(mListener); - mListener = nullptr; - - return CHIP_NO_ERROR; -} - -CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseConnection() -{ - VerifyOrReturnError(mConnection, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDispatchQueue, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); - - nw_connection_cancel(mConnection); - dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); - nw_release(mConnection); - mConnection = nullptr; - - return CHIP_NO_ERROR; -} - -} // namespace Inet -} // namespace chip diff --git a/src/inet/UDPEndPointImplNetworkFramework.h b/src/inet/UDPEndPointImplNetworkFramework.h index 55c5ef1812..0e8f7dda68 100644 --- a/src/inet/UDPEndPointImplNetworkFramework.h +++ b/src/inet/UDPEndPointImplNetworkFramework.h @@ -56,14 +56,16 @@ class UDPEndPointImplNetworkFramework : public UDPEndPoint, public EndPointState dispatch_queue_t mListenerQueue; nw_connection_t mConnection; dispatch_semaphore_t mConnectionSemaphore; - dispatch_queue_t mDispatchQueue; + dispatch_queue_t mConnectionQueue; dispatch_semaphore_t mSendSemaphore; + dispatch_queue_t mSystemQueue; CHIP_ERROR ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters); CHIP_ERROR StartListener(); CHIP_ERROR GetConnection(const IPPacketInfo * aPktInfo); - CHIP_ERROR GetEndPoint(nw_endpoint_t & aEndpoint, const IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort); - CHIP_ERROR StartConnection(nw_connection_t & aConnection); + nw_endpoint_t GetEndPoint(const IPAddressType aAddressType, const IPAddress & aAddress, uint16_t aPort, + InterfaceId interfaceIndex = InterfaceId::Null()); + CHIP_ERROR StartConnection(nw_connection_t aConnection); void GetPacketInfo(const nw_connection_t & aConnection, IPPacketInfo & aPacketInfo); void HandleDataReceived(const nw_connection_t & aConnection); CHIP_ERROR ReleaseListener(); diff --git a/src/inet/UDPEndPointImplNetworkFramework.mm b/src/inet/UDPEndPointImplNetworkFramework.mm new file mode 100644 index 0000000000..070048538c --- /dev/null +++ b/src/inet/UDPEndPointImplNetworkFramework.mm @@ -0,0 +1,655 @@ +/* + * + * Copyright (c) 2020-2024 Project CHIP Authors + * Copyright (c) 2018 Google LLC. + * Copyright (c) 2013-2018 Nest Labs, Inc. + * + * 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. + */ + +/** + * This file implements Inet::UDPEndPoint using Network Framework. + */ + +#if !__has_feature(objc_arc) +#error This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC). +#endif + +#include +#include + +#include + +#define INET_PORTSTRLEN 6 + +#define NETWORK_FRAMEWORK_DEBUG 0 + +namespace { +#if !NETWORK_FRAMEWORK_DEBUG +void DebugPrintListenerState(nw_listener_state_t state) {}; +void DebugPrintConnectionState(nw_connection_state_t state) {}; +void DebugPrintConnection(const nw_connection_t aConnection) {}; +#else +constexpr const char * kNilConnection = "The connection is nil."; +constexpr const char * kNilPath = "The connection path is nil."; +constexpr const char * kNilPathSourceEndPoint = "The connection path source endpoint is nil."; +constexpr const char * kNilPathDestinationEndPoint = "The connection path destination endpoint is nil."; +constexpr const char * kPathStatusInvalid = "This path is not valid."; +constexpr const char * kPathStatusUnsatisfied = "The path is not available for use."; +constexpr const char * kPathStatusSatisfied = "The path is available to establish connections and send data."; +constexpr const char * kPathStatusSatisfiable = "The path is not currently available, but establishing a new connection may activate the path."; + +constexpr const char * kListenerStateInvalid = "Listener: Invalid"; +constexpr const char * kListenerStateWaiting = "Listener: Waiting"; +constexpr const char * kListenerStateFailed = "Listener: Failed"; +constexpr const char * kListenerStateReady = "Listener: Ready"; +constexpr const char * kListenerStateCancelled = "Listener: Cancelled"; + +constexpr const char * kConnectionStateInvalid = "Connection: Invalid"; +constexpr const char * kConnectionStateWaiting = "Connection: Waiting"; +constexpr const char * kConnectionStatePreparing = "Connection: Preparing"; +constexpr const char * kConnectionStateFailed = "Connection: Failed"; +constexpr const char * kConnectionStateReady = "Connection: Ready"; +constexpr const char * kConnectionStateCancelled = "Connection: Cancelled"; + +void DebugPrintConnectionState(nw_connection_state_t state) +{ + const char * str = nullptr; + + switch (state) { + case nw_connection_state_invalid: + str = kConnectionStateInvalid; + break; + case nw_connection_state_preparing: + str = kConnectionStatePreparing; + break; + case nw_connection_state_waiting: + str = kConnectionStateWaiting; + break; + case nw_connection_state_failed: + str = kConnectionStateFailed; + break; + case nw_connection_state_ready: + str = kConnectionStateReady; + break; + case nw_connection_state_cancelled: + str = kConnectionStateCancelled; + break; + default: + chipDie(); + } + + ChipLogDetail(Inet, "%s", str); +} + +void DebugPrintListenerState(nw_listener_state_t state) +{ + const char * str = nullptr; + + switch (state) { + case nw_listener_state_invalid: + str = kListenerStateInvalid; + break; + case nw_listener_state_waiting: + str = kListenerStateWaiting; + break; + case nw_listener_state_failed: + str = kListenerStateFailed; + break; + case nw_listener_state_ready: + str = kListenerStateReady; + break; + case nw_listener_state_cancelled: + str = kListenerStateCancelled; + break; + default: + chipDie(); + } + + ChipLogDetail(Inet, "%s", str); +} + +void DebugPrintConnectionPathStatus(nw_path_t path) +{ + const char * str = nullptr; + + __auto_type status = nw_path_get_status(path); + switch (status) { + case nw_path_status_invalid: + str = kPathStatusInvalid; + break; + case nw_path_status_unsatisfied: + str = kPathStatusUnsatisfied; + break; + case nw_path_status_satisfied: + str = kPathStatusSatisfied; + break; + case nw_path_status_satisfiable: + str = kPathStatusSatisfiable; + break; + default: + chipDie(); + } + + ChipLogError(Inet, "%s", str); +} + +void DebugPrintConnection(const nw_connection_t aConnection) +{ + VerifyOrReturn(nil != aConnection, ChipLogError(Inet, "%s", kNilConnection)); + + __auto_type path = nw_connection_copy_current_path(aConnection); + VerifyOrReturn(nil != path, ChipLogError(Inet, "%s", kNilPath)); + DebugPrintConnectionPathStatus(path); + + __auto_type srcEndPoint = nw_path_copy_effective_local_endpoint(path); + VerifyOrReturn(nil != srcEndPoint, ChipLogError(Inet, "%s", kNilPathSourceEndPoint)); + + __auto_type dstEndPoint = nw_path_copy_effective_remote_endpoint(path); + VerifyOrReturn(nil != dstEndPoint, ChipLogError(Inet, "%s", kNilPathDestinationEndPoint)); + + const __auto_type * srcAddress = nw_endpoint_copy_address_string(srcEndPoint); + const __auto_type srcPort = nw_endpoint_get_port(srcEndPoint); + const __auto_type * dstAddress = nw_endpoint_copy_address_string(dstEndPoint); + const __auto_type dstPort = nw_endpoint_get_port(dstEndPoint); + + ChipLogError(Inet, "Connection source: %s:%u destination: %s:%u", srcAddress, srcPort, dstAddress, dstPort); +} +#endif +} + +namespace chip { +namespace Inet { + + CHIP_ERROR UDPEndPointImplNetworkFramework::BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, + InterfaceId intfId) + { +#if NETWORK_FRAMEWORK_DEBUG + ChipLogError(Inet, "%s (%p)", __func__, this); +#endif + + VerifyOrReturnError(!intfId.IsPresent(), CHIP_ERROR_NOT_IMPLEMENTED); + + __auto_type configure_tls = NW_PARAMETERS_DISABLE_PROTOCOL; + __auto_type parameters = nw_parameters_create_secure_udp(configure_tls, NW_PARAMETERS_DEFAULT_CONFIGURATION); + VerifyOrReturnError(nullptr != parameters, CHIP_ERROR_INVALID_ARGUMENT); + + // Note: The ConfigureProtocol function uses nw_ip_options_set_version to set the IP version for this endpoint. + // + // This works as expected when the IPAddress is specified. However, when using a wildcard address (chip::Inet::IPAddressType::kAny) + // for an IPv6 socket, the specified IP version (nw_ip_version_6) may be ignored, allowing both IPv4 and IPv6 connections. + ReturnErrorOnFailure(ConfigureProtocol(addressType, parameters)); + + // Note: Network.framework does not provide an API to set the SO_REUSEPORT socket option. + // This limitation is not an issue when the port is set to 0, as the platform will choose a random port. + // + // However, when both INET_CONFIG_ENABLE_IPV4 and CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY are enabled, + // the system attempts to create two endpoints—one over IPv6 and another over IPv4—both using the same port + // specified by CHIP_UDC_PORT. + // + // This results in a binding failure due to "Address already in use" since both IPv4 and IPv6 endpoints + // try to use the same port. + // + // A potential solution would be to define separate ports for IPv4 and IPv6 (e.g., CHIP_UDC_PORT_IPv4 and CHIP_UDC_PORT_IPv6). + // For now, as a workaround, we set the port to 0 for IPv4 when a specific port is needed, allowing the platform to + // auto-assign an available port and avoid the conflict. + if (IPAddressType::kIPv4 == addressType && port != 0) { + port = 0; + } + + __auto_type endpoint = GetEndPoint(addressType, address, port); + VerifyOrReturnError(nullptr != endpoint, CHIP_ERROR_INTERNAL); + nw_parameters_set_local_endpoint(parameters, endpoint); + + mConnectionQueue = dispatch_queue_create("inet_dispatch_global", DISPATCH_QUEUE_SERIAL); + VerifyOrReturnError(nullptr != mConnectionQueue, CHIP_ERROR_NO_MEMORY); + + mConnectionSemaphore = dispatch_semaphore_create(0); + VerifyOrReturnError(nullptr != mConnectionSemaphore, CHIP_ERROR_NO_MEMORY); + + mSendSemaphore = dispatch_semaphore_create(0); + VerifyOrReturnError(nullptr != mSendSemaphore, CHIP_ERROR_NO_MEMORY); + + mSystemQueue = static_cast(GetSystemLayer()).GetDispatchQueue(); + mAddrType = addressType; + mConnection = nullptr; + mParameters = parameters; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::BindInterfaceImpl(IPAddressType addrType, InterfaceId intfId) + { + return INET_ERROR_UNKNOWN_INTERFACE; + } + + InterfaceId UDPEndPointImplNetworkFramework::GetBoundInterface() const + { + return InterfaceId::Null(); + } + + uint16_t UDPEndPointImplNetworkFramework::GetBoundPort() const + { + __auto_type endpoint = nw_parameters_copy_local_endpoint(mParameters); + return nw_endpoint_get_port(endpoint); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ListenImpl() + { + return StartListener(); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::SendMsgImpl(const IPPacketInfo * pktInfo, System::PacketBufferHandle && msg) + { +#if NETWORK_FRAMEWORK_DEBUG + ChipLogError(Inet, "%s (%p)", __func__, this); +#endif + + // Ensure we have an actual message to send. + VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT); + + // Ensure the destination address type is compatible with the endpoint address type. + VerifyOrReturnError(mAddrType == pktInfo->DestAddress.Type(), CHIP_ERROR_INVALID_ARGUMENT); + + // For now the entire message must fit within a single buffer. + VerifyOrReturnError(msg->Next() == nullptr, CHIP_ERROR_MESSAGE_TOO_LONG); + + ReturnErrorOnFailure(GetConnection(pktInfo)); + + // Send a message, and wait for it to be dispatched. + __auto_type content = dispatch_data_create(msg->Start(), msg->DataLength(), mSystemQueue, DISPATCH_DATA_DESTRUCTOR_DEFAULT); + + // If there is a current message pending and the state of the network connection changes (e.g switch to a + // different network) the connection will enter a nw_connection_state_failed state and the completion handler + // will never be called. In such cases a signal is sent from the connection state change handler to release + // the semaphore. In this case the CHIP_ERROR will not update with the result of the completion handler. + // To make sure our caller knows that sending a message has failed the following code assumes there is an error + // _unless_ the completion handler says otherwise. + __block CHIP_ERROR err = CHIP_ERROR_UNEXPECTED_EVENT; + nw_connection_send(mConnection, content, NW_CONNECTION_DEFAULT_MESSAGE_CONTEXT, true, ^(nw_error_t error) { + if (error) { + err = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); + } else { + err = CHIP_NO_ERROR; + } + dispatch_semaphore_signal(mSendSemaphore); + }); + + dispatch_semaphore_wait(mSendSemaphore, DISPATCH_TIME_FOREVER); + + return err; + } + + void UDPEndPointImplNetworkFramework::CloseImpl() + { + ReleaseAll(); + } + + void UDPEndPointImplNetworkFramework::ReleaseAll() + { + + OnMessageReceived = nullptr; + OnReceiveError = nullptr; + + ReleaseConnection(); + ReleaseListener(); + + mParameters = nullptr; + + mConnectionQueue = nullptr; + mConnectionSemaphore = nullptr; + + mListenerQueue = nullptr; + mListenerSemaphore = nullptr; + + mSendSemaphore = nullptr; + } + + void UDPEndPointImplNetworkFramework::Free() + { + Close(); + Release(); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + +#if INET_CONFIG_ENABLE_IPV4 + CHIP_ERROR UDPEndPointImplNetworkFramework::IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, + bool join) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } +#endif // INET_CONFIG_ENABLE_IPV4 + + CHIP_ERROR UDPEndPointImplNetworkFramework::IPv6JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, + bool join) + { + return CHIP_ERROR_NOT_IMPLEMENTED; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ConfigureProtocol(IPAddressType aAddressType, const nw_parameters_t & aParameters) + { + CHIP_ERROR err = CHIP_NO_ERROR; + + __auto_type protocolStack = nw_parameters_copy_default_protocol_stack(aParameters); + __auto_type ipOptions = nw_protocol_stack_copy_internet_protocol(protocolStack); + + switch (aAddressType) { + + case IPAddressType::kIPv6: + nw_ip_options_set_version(ipOptions, nw_ip_version_6); + break; + +#if INET_CONFIG_ENABLE_IPV4 + case IPAddressType::kIPv4: + nw_ip_options_set_version(ipOptions, nw_ip_version_4); + break; +#endif // INET_CONFIG_ENABLE_IPV4 + + default: + err = INET_ERROR_WRONG_ADDRESS_TYPE; + break; + } + + return err; + } + + void UDPEndPointImplNetworkFramework::GetPacketInfo(const nw_connection_t & aConnection, IPPacketInfo & aPacketInfo) + { + nw_path_t path = nw_connection_copy_current_path(aConnection); + nw_endpoint_t dest_endpoint = nw_path_copy_effective_local_endpoint(path); + nw_endpoint_t src_endpoint = nw_path_copy_effective_remote_endpoint(path); + + aPacketInfo.Clear(); + + // TODO Handle return value of IPAddress::GetIPAddressFromSockAdd + const auto * srcAddress = nw_endpoint_get_address(src_endpoint); + IPAddress::GetIPAddressFromSockAddr(*srcAddress, aPacketInfo.SrcAddress); + + // TODO Handle return value of IPAddress::GetIPAddressFromSockAdd + const auto * dstAddress = nw_endpoint_get_address(dest_endpoint); + IPAddress::GetIPAddressFromSockAddr(*dstAddress, aPacketInfo.DestAddress); + + aPacketInfo.SrcPort = nw_endpoint_get_port(src_endpoint); + aPacketInfo.DestPort = nw_endpoint_get_port(dest_endpoint); + +#if NETWORK_FRAMEWORK_DEBUG + char srcAddrStr[IPAddress::kMaxStringLength + 1 /*null terminator */]; + char dstAddrStr[IPAddress::kMaxStringLength + 1 /*null terminator */]; + aPacketInfo.SrcAddress.ToString(srcAddrStr); + aPacketInfo.DestAddress.ToString(dstAddrStr); + ChipLogError(Inet, "Packet received from %s to %s", srcAddrStr, dstAddrStr); +#endif + } + + nw_endpoint_t UDPEndPointImplNetworkFramework::GetEndPoint(const IPAddressType aAddressType, + const IPAddress & aAddress, uint16_t aPort, InterfaceId interfaceIndex) + { + char addrStr[IPAddress::kMaxStringLength + 1 /*%*/ + InterfaceId::kMaxIfNameLength + 1 /*null terminator */]; + char portStr[INET_PORTSTRLEN]; + + // Note: aAddress.ToString will return the IPv6 Any address if the address type is Any, but that's not what + // we want if the local endpoint is IPv4. +#if INET_CONFIG_ENABLE_IPV4 + if (aAddressType == IPAddressType::kIPv4 && aAddress.Type() == IPAddressType::kAny) { + const IPAddress anyAddr = IPAddress(aAddress.ToIPv4()); + anyAddr.ToString(addrStr); + } else +#endif // INET_CONFIG_ENABLE_IPV4 + { + aAddress.ToString(addrStr); + if (interfaceIndex != InterfaceId::Null()) { + char interface[InterfaceId::kMaxIfNameLength + 1] = {}; // +1 to prepend '%' + interface[0] = '%'; + interface[1] = 0; + CHIP_ERROR err = interfaceIndex.GetInterfaceName(interface + 1, sizeof(interface) - 1); + if (err != CHIP_NO_ERROR) { + Platform::CopyString(interface, sizeof(interface), "%(err)"); + } + strncat(addrStr, interface, sizeof(addrStr) - strlen(addrStr) - 1); + } + } + + snprintf(portStr, sizeof(portStr), "%u", aPort); + + char * target = addrStr; + +#if NETWORK_FRAMEWORK_DEBUG + ChipLogError(Inet, "Create endpoint for ip(%s) port(%s)", target, portStr); +#endif + return nw_endpoint_create_host(target, portStr); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::GetConnection(const IPPacketInfo * aPktInfo) + { + VerifyOrReturnError(nullptr != mParameters, CHIP_ERROR_INCORRECT_STATE); + + if (mConnection) { + __auto_type path = nw_connection_copy_current_path(mConnection); + __auto_type remote_endpoint = nw_path_copy_effective_remote_endpoint(path); + // TODO Handle return value of IPAddress::GetIPAddressFromSockAdd + IPAddress remote_address; + IPAddress::GetIPAddressFromSockAddr(*nw_endpoint_get_address(remote_endpoint), remote_address); + + const uint16_t remote_port = nw_endpoint_get_port(remote_endpoint); + const bool isDifferentEndPoint = aPktInfo->DestPort != remote_port || aPktInfo->DestAddress != remote_address; + // Return without doing anything if we are not changing our endpoint. + VerifyOrReturnError(isDifferentEndPoint, CHIP_NO_ERROR); + + ReturnErrorOnFailure(ReleaseConnection()); + } + + __auto_type endpoint = GetEndPoint(mAddrType, aPktInfo->DestAddress, aPktInfo->DestPort, aPktInfo->Interface); + VerifyOrReturnError(nullptr != endpoint, CHIP_ERROR_INCORRECT_STATE); + + __auto_type connection = nw_connection_create(endpoint, mParameters); + VerifyOrReturnError(nullptr != connection, CHIP_ERROR_INCORRECT_STATE); + + return StartConnection(connection); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::StartListener() + { + VerifyOrReturnError(nullptr == mListener, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr == mListenerSemaphore, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr == mListenerQueue, CHIP_ERROR_INCORRECT_STATE); + + __auto_type listener = nw_listener_create(mParameters); + VerifyOrReturnError(nullptr != listener, CHIP_ERROR_INCORRECT_STATE); + + mListenerSemaphore = dispatch_semaphore_create(0); + VerifyOrReturnError(nullptr != mListenerSemaphore, CHIP_ERROR_NO_MEMORY); + + mListenerQueue = dispatch_queue_create("inet_dispatch_listener", DISPATCH_QUEUE_CONCURRENT); + VerifyOrReturnError(nullptr != mListenerQueue, CHIP_ERROR_NO_MEMORY); + + nw_listener_set_queue(listener, mListenerQueue); + + nw_listener_set_new_connection_handler(listener, ^(nw_connection_t connection) { + ReleaseConnection(); + StartConnection(connection); + }); + + __block CHIP_ERROR err = CHIP_NO_ERROR; + nw_listener_set_state_changed_handler(listener, ^(nw_listener_state_t state, nw_error_t error) { + DebugPrintListenerState(state); + + switch (state) { + case nw_listener_state_invalid: + err = CHIP_ERROR_INCORRECT_STATE; + nw_listener_cancel(listener); + break; + + case nw_listener_state_waiting: + // Nothing to do. + break; + + case nw_listener_state_failed: + err = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); + ChipLogError(Inet, "Error: %s", chip::ErrorStr(err)); + break; + + case nw_listener_state_ready: + err = CHIP_NO_ERROR; + dispatch_semaphore_signal(mListenerSemaphore); + break; + + case nw_listener_state_cancelled: + if (err == CHIP_NO_ERROR) { + err = CHIP_ERROR_CONNECTION_ABORTED; + } + + dispatch_semaphore_signal(mListenerSemaphore); + break; + } + }); + + nw_listener_start(listener); + dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); + + if (CHIP_NO_ERROR == err) { + mListener = listener; + } + + return err; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::StartConnection(nw_connection_t aConnection) + { + __block CHIP_ERROR err = CHIP_NO_ERROR; + + nw_connection_set_queue(aConnection, mConnectionQueue); + + nw_connection_set_state_changed_handler(aConnection, ^(nw_connection_state_t state, nw_error_t error) { + DebugPrintConnectionState(state); + + switch (state) { + case nw_connection_state_invalid: + err = CHIP_ERROR_INCORRECT_STATE; + nw_connection_cancel(aConnection); + break; + + case nw_connection_state_preparing: + err = CHIP_ERROR_INCORRECT_STATE; + break; + + case nw_connection_state_waiting: + nw_connection_cancel(aConnection); + break; + + case nw_connection_state_failed: + err = CHIP_ERROR_POSIX(nw_error_get_error_code(error)); + break; + + case nw_connection_state_ready: + err = CHIP_NO_ERROR; + dispatch_semaphore_signal(mConnectionSemaphore); + break; + + case nw_connection_state_cancelled: + if (err == CHIP_NO_ERROR) { + err = CHIP_ERROR_CONNECTION_ABORTED; + } + + dispatch_semaphore_signal(mConnectionSemaphore); + break; + } + }); + + nw_connection_start(aConnection); + dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); + + if (CHIP_NO_ERROR == err) { + DebugPrintConnection(aConnection); + + mConnection = aConnection; + HandleDataReceived(mConnection); + } + return err; + } + + void UDPEndPointImplNetworkFramework::HandleDataReceived(const nw_connection_t & aConnection) + { + nw_connection_receive_completion_t handler = ^(dispatch_data_t content, nw_content_context_t context, bool is_complete, nw_error_t receive_error) { + dispatch_block_t schedule_next_receive = ^{ + if (receive_error == nullptr) { + HandleDataReceived(aConnection); + } else if (OnReceiveError != nullptr) { + __auto_type error_domain = nw_error_get_error_domain(receive_error); + errno = nw_error_get_error_code(receive_error); + if (!(error_domain == nw_error_domain_posix && errno == ECANCELED)) { + CHIP_ERROR error = CHIP_ERROR_POSIX(errno); + IPPacketInfo packetInfo; + GetPacketInfo(aConnection, packetInfo); + dispatch_async(mSystemQueue, ^{ + OnReceiveError((UDPEndPoint *) this, error, &packetInfo); + }); + } + } + }; + + if (content != nullptr && OnMessageReceived != nullptr) { + size_t count = dispatch_data_get_size(content); + auto packetBufferHandle = System::PacketBufferHandle::New(count); + auto * packetBuffer = std::move(packetBufferHandle).UnsafeRelease(); + dispatch_data_apply(content, ^(dispatch_data_t data, size_t offset, const void * buffer, size_t size) { + memmove(packetBuffer->Start() + offset, buffer, size); + return true; + }); + packetBuffer->SetDataLength(count); + + IPPacketInfo packetInfo; + GetPacketInfo(aConnection, packetInfo); + dispatch_async(mSystemQueue, ^{ + auto handle = System::PacketBufferHandle::Adopt(packetBuffer); + OnMessageReceived((UDPEndPoint *) this, std::move(handle), &packetInfo); + }); + } + + schedule_next_receive(); + }; + + nw_connection_receive_message(aConnection, handler); + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseListener() + { + VerifyOrReturnError(nullptr != mListener, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionQueue, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); + + nw_listener_cancel(mListener); + dispatch_semaphore_wait(mListenerSemaphore, DISPATCH_TIME_FOREVER); + mListener = nullptr; + + return CHIP_NO_ERROR; + } + + CHIP_ERROR UDPEndPointImplNetworkFramework::ReleaseConnection() + { + VerifyOrReturnError(nullptr != mConnection, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionQueue, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(nullptr != mConnectionSemaphore, CHIP_ERROR_INCORRECT_STATE); + + nw_connection_cancel(mConnection); + dispatch_semaphore_wait(mConnectionSemaphore, DISPATCH_TIME_FOREVER); + mConnection = nullptr; + + return CHIP_NO_ERROR; + } + +} // namespace Inet +} // namespace chip diff --git a/src/inet/inet.gni b/src/inet/inet.gni index 1c19551da3..ea66c3df3f 100644 --- a/src/inet/inet.gni +++ b/src/inet/inet.gni @@ -26,11 +26,18 @@ declare_args() { # Enable TCP endpoint. chip_inet_config_enable_tcp_endpoint = true + # TODO: Set to false when using Network.framework until a Network.framework TCP endpoint backend is implemented. + if (chip_system_config_use_network_framework) { + chip_inet_config_enable_tcp_endpoint = false + } + # Inet implementation type. if (chip_system_config_use_open_thread_inet_endpoints) { chip_system_config_inet = "OpenThread" } else if (chip_system_config_use_lwip) { chip_system_config_inet = "LwIP" + } else if (chip_system_config_use_network_framework) { + chip_system_config_inet = "NetworkFramework" } else { chip_system_config_inet = "Sockets" } diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index fca3472826..a775d2b58f 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -618,13 +618,13 @@ #define _CHIP_CONFIG_IsPlatformLwIPErrorNonCritical(CODE) 0 #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #define _CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical(CODE) \ ((CODE) == CHIP_ERROR_POSIX(EHOSTUNREACH) || (CODE) == CHIP_ERROR_POSIX(ENETUNREACH) || \ (CODE) == CHIP_ERROR_POSIX(EADDRNOTAVAIL) || (CODE) == CHIP_ERROR_POSIX(EPIPE)) -#else // !CHIP_SYSTEM_CONFIG_USE_SOCKETS +#else // !(CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) #define _CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical(CODE) 0 -#endif // !CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // !(CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) #define CHIP_CONFIG_IsPlatformErrorNonCritical(CODE) \ (_CHIP_CONFIG_IsPlatformPOSIXErrorNonCritical(CODE) || _CHIP_CONFIG_IsPlatformLwIPErrorNonCritical(CODE)) diff --git a/src/system/BUILD.gn b/src/system/BUILD.gn index a8d15cf83f..3de5ea84be 100644 --- a/src/system/BUILD.gn +++ b/src/system/BUILD.gn @@ -99,7 +99,7 @@ buildconfig_header("system_buildconfig") { "CHIP_SYSTEM_CONFIG_USE_LWIP=${chip_system_config_use_lwip}", "CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT=${chip_system_config_use_open_thread_inet_endpoints}", "CHIP_SYSTEM_CONFIG_USE_SOCKETS=${chip_system_config_use_sockets}", - "CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK=false", + "CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK=${chip_system_config_use_network_framework}", "CHIP_SYSTEM_CONFIG_POSIX_LOCKING=${chip_system_config_posix_locking}", "CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING=${chip_system_config_freertos_locking}", "CHIP_SYSTEM_CONFIG_MBED_LOCKING=${chip_system_config_mbed_locking}", diff --git a/src/system/SystemConfig.h b/src/system/SystemConfig.h index 58339df4be..2fe0823922 100644 --- a/src/system/SystemConfig.h +++ b/src/system/SystemConfig.h @@ -768,7 +768,7 @@ struct LwIPEvent; * Defaults to enabled on platforms that use sockets other than Zephyr sockets. */ #ifndef CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && !CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKETS +#if (CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK) && !CHIP_SYSTEM_CONFIG_USE_ZEPHYR_SOCKETS #define CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS 1 #else #define CHIP_SYSTEM_CONFIG_USE_POSIX_SOCKETS 0 diff --git a/src/system/SystemLayer.h b/src/system/SystemLayer.h index 75878ce6a8..9314ccd560 100644 --- a/src/system/SystemLayer.h +++ b/src/system/SystemLayer.h @@ -40,10 +40,10 @@ #include #include -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #include #include -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_USE_NETWORK_FRAMEWORK #if CHIP_SYSTEM_CONFIG_USE_DISPATCH #include @@ -235,7 +235,7 @@ class LayerFreeRTOS : public Layer #endif // CHIP_SYSTEM_CONFIG_USE_LWIP -#if CHIP_SYSTEM_CONFIG_USE_SOCKETS +#if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK class LayerSockets : public Layer { @@ -356,7 +356,7 @@ class LayerSocketsLoop : public LayerSockets decltype(EventLoopHandler::mState) & LoopHandlerState(EventLoopHandler & handler) { return handler.mState; } }; -#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } // namespace System } // namespace chip diff --git a/src/system/SystemLayerImplSelect.cpp b/src/system/SystemLayerImplSelect.cpp index fe025a5765..52354f99d8 100644 --- a/src/system/SystemLayerImplSelect.cpp +++ b/src/system/SystemLayerImplSelect.cpp @@ -67,10 +67,10 @@ CHIP_ERROR LayerImplSelect::Init() mHandleSelectThread = PTHREAD_NULL; #endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK // Create an event to allow an arbitrary thread to wake the thread in the select loop. ReturnErrorOnFailure(mWakeEvent.Open(*this)); -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK VerifyOrReturnError(mLayerState.SetInitialized(), CHIP_ERROR_INCORRECT_STATE); return CHIP_NO_ERROR; @@ -116,9 +116,9 @@ void LayerImplSelect::Shutdown() mTimerPool.ReleaseAll(); #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK mWakeEvent.Close(*this); -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK mLayerState.ResetFromShuttingDown(); // Return to uninitialized state to permit re-initialization. } @@ -127,6 +127,8 @@ void LayerImplSelect::Signal() { #if CHIP_SYSTEM_CONFIG_USE_LIBEV ChipLogError(DeviceLayer, "Signal() should not be called in CHIP_SYSTEM_CONFIG_USE_LIBEV builds (might be ok in tests)"); +#elif CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + ChipLogError(DeviceLayer, "Signal() should not be called in CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK builds"); #else /* * Wake up the I/O thread by writing a single byte to the wake pipe. @@ -151,7 +153,7 @@ void LayerImplSelect::Signal() ChipLogError(chipSystemLayer, "System wake event notify failed: %" CHIP_ERROR_FORMAT, status.Format()); } -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) @@ -188,6 +190,9 @@ CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallba dispatch_resume(timerSource); return CHIP_NO_ERROR; } +#if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + return CHIP_ERROR_INTERNAL; +#endif // CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #elif CHIP_SYSTEM_CONFIG_USE_LIBEV VerifyOrDie(mLibEvLoopP != nullptr); ev_timer_init(&timer->mLibEvTimer, &LayerImplSelect::HandleLibEvTimer, 1, 0); @@ -205,15 +210,18 @@ CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallba ev_timer_start(mLibEvLoopP, &timer->mLibEvTimer); return CHIP_NO_ERROR; #endif -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV - // Note: dispatch based implementation needs this as fallback, but not LIBEV (and dead code is not allowed with -Werror) +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + // Note: The dispatch-based implementation (using sockets but not Network.framework) requires this as a fallback + // for testing purposes. However, it is not needed for LIBEV or when using Network.framework (which lacks a testing + // configuration). Since dead code is also not allowed with -Werror, we need to ifdef this code out + // in those configurations. if (mTimerList.Add(timer) == timer) { // The new timer is the earliest, so the time until the next event has probably changed. Signal(); } return CHIP_NO_ERROR; -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } CHIP_ERROR LayerImplSelect::ExtendTimerTo(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) @@ -290,8 +298,8 @@ void LayerImplSelect::CancelTimer(TimerCompleteCallback onComplete, void * appSt #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV mTimerPool.Release(timer); -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV - // LIBEV has no I/O wakeup thread, so must not call Signal() +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + // Neither LIBEV nor CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK builds include an I/O wakeup thread, so must not call Signal(). Signal(); #endif } @@ -311,6 +319,9 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void }); return CHIP_NO_ERROR; } +#if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + return CHIP_ERROR_INTERNAL; +#endif // CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK #elif CHIP_SYSTEM_CONFIG_USE_LIBEV // schedule as timer with no delay, but do NOT cancel previous timers with same onComplete/appState! TimerList::Node * timer = mTimerPool.Create(*this, SystemClock().GetMonotonicTimestamp(), onComplete, appState); @@ -324,8 +335,11 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void ev_timer_start(mLibEvLoopP, &timer->mLibEvTimer); return CHIP_NO_ERROR; #endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH/LIBEV -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV - // Note: dispatch based implementation needs this as fallback, but not LIBEV (and dead code is not allowed with -Werror) +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK + // Note: The dispatch-based implementation (using sockets but not Network.framework) requires this as a fallback + // for testing purposes. However, it is not needed for LIBEV or when using Network.framework (which lacks a testing + // configuration). Since dead code is also not allowed with -Werror, we need to ifdef this code out + // in those configurations. // Ideally we would not use a timer here at all, but if we try to just // ScheduleLambda the lambda needs to capture the following: // 1) onComplete @@ -360,7 +374,7 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void Signal(); } return CHIP_NO_ERROR; -#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV +#endif // !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK } CHIP_ERROR LayerImplSelect::StartWatchingSocket(int fd, SocketWatchToken * tokenOut) diff --git a/src/system/SystemLayerImplSelect.h b/src/system/SystemLayerImplSelect.h index ce34ece011..d2f8c880ee 100644 --- a/src/system/SystemLayerImplSelect.h +++ b/src/system/SystemLayerImplSelect.h @@ -158,7 +158,7 @@ class LayerImplSelect : public LayerSocketsLoop int mSelectResult; ObjectLifeCycle mLayerState; -#if !CHIP_SYSTEM_CONFIG_USE_LIBEV +#if !CHIP_SYSTEM_CONFIG_USE_LIBEV && !CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK WakeEvent mWakeEvent; #endif diff --git a/src/system/system.gni b/src/system/system.gni index 61cd52fa32..e58f329146 100644 --- a/src/system/system.gni +++ b/src/system/system.gni @@ -20,8 +20,8 @@ declare_args() { # Use the lwIP library. chip_system_config_use_lwip = chip_with_lwip && current_os == "freertos" - # Use BSD/POSIX socket API. - chip_system_config_use_sockets = current_os != "freertos" + # Use Network.framework API + chip_system_config_use_network_framework = false # Mutex implementation: posix, freertos, none. chip_system_config_locking = "" @@ -36,13 +36,21 @@ declare_args() { chip_system_config_use_open_thread_inet_endpoints = false } +declare_args() { + # Use BSD/POSIX socket API. + chip_system_config_use_sockets = + current_os != "freertos" && !chip_system_config_use_network_framework +} + declare_args() { # do not use libev by default chip_system_config_use_libev = false # use the dispatch library on darwin targets - chip_system_config_use_dispatch = chip_system_config_use_sockets && - (current_os == "mac" || current_os == "ios") + chip_system_config_use_dispatch = + (chip_system_config_use_sockets || + chip_system_config_use_network_framework) && + (current_os == "mac" || current_os == "ios") } declare_args() { From b8898ab793578b5bfc53578ba0df519fd22cca60 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 14 Nov 2024 18:26:07 -0500 Subject: [PATCH 010/219] Move more of the MTRAttributeValueWaiter logic into the waiter. (#36416) * Move more of the MTRAttributeValueWaiter logic into the waiter. This logic should not live in MTRDevice. * Address review comments. --- .../Framework/CHIP/MTRAttributeValueWaiter.mm | 77 +++++++++++++++---- .../CHIP/MTRAttributeValueWaiter_Internal.h | 10 ++- src/darwin/Framework/CHIP/MTRDevice.mm | 63 ++++----------- .../Framework/CHIP/MTRDevice_Internal.h | 2 +- 4 files changed, 87 insertions(+), 65 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm index 10d0b9f8e1..930bbd790c 100644 --- a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm +++ b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.mm @@ -15,12 +15,15 @@ */ #import +#import #import #import "MTRAttributeValueWaiter_Internal.h" #import "MTRDevice_Internal.h" +#import "MTRError_Internal.h" #import "MTRLogging_Internal.h" +#import "MTRUnfairLock.h" @implementation MTRAwaitedAttributeState - (instancetype)initWithValue:(MTRDeviceDataValueDictionary)value @@ -40,10 +43,14 @@ @interface MTRAttributeValueWaiter () // Protected by the MTRDevice's lock. @property (nonatomic, readwrite, retain) dispatch_queue_t queue; @property (nonatomic, readwrite, copy, nullable) MTRStatusCompletion completion; +@property (nonatomic, retain, readwrite, nullable) dispatch_source_t expirationTimer; @property (nonatomic, readonly, retain) MTRDevice * device; @end -@implementation MTRAttributeValueWaiter +@implementation MTRAttributeValueWaiter { + // Protects queue/completion and expirationTimer. + os_unfair_lock _lock; +} - (instancetype)initWithDevice:(MTRDevice *)device values:(NSDictionary *)values queue:(dispatch_queue_t)queue completion:(MTRStatusCompletion)completion { @@ -58,6 +65,7 @@ - (instancetype)initWithDevice:(MTRDevice *)device values:(NSDictionary(timeout * static_cast(NSEC_PER_SEC))), DISPATCH_TIME_FOREVER, + // Allow .5 seconds of leeway; should be plenty, in practice. + static_cast(0.5 * static_cast(NSEC_PER_SEC))); + + mtr_weakify(self); + dispatch_source_set_event_handler(timerSource, ^{ + dispatch_source_cancel(timerSource); + mtr_strongify(self); + if (self != nil) { + [self.device _forgetAttributeWaiter:self]; + [self _notifyWithError:[MTRError errorForCHIPErrorCode:CHIP_ERROR_TIMEOUT]]; + } + }); + + { + std::lock_guard lock(_lock); + self.expirationTimer = timerSource; + } + + dispatch_resume(timerSource); +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %@>", NSStringFromClass(self.class), self.UUID]; diff --git a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h index 8d4a799969..a23af1d06d 100644 --- a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h +++ b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter_Internal.h @@ -37,7 +37,6 @@ MTR_DIRECT_MEMBERS @interface MTRAttributeValueWaiter () @property (nonatomic, readonly) BOOL allValuesSatisfied; -@property (nonatomic, retain, readwrite, nullable) dispatch_source_t expirationTimer; - (instancetype)initWithDevice:(MTRDevice *)device values:(NSDictionary *)values queue:(dispatch_queue_t)queue completion:(MTRStatusCompletion)completion; @@ -46,6 +45,15 @@ MTR_DIRECT_MEMBERS - (void)_notifyWithError:(NSError * _Nullable)error; +// Starts the timer for our timeout, using the device's queue as the dispatch +// queuue for the timer firing. +- (void)_startTimerWithTimeout:(NSTimeInterval)timeout; + +// Cancels the waiter without trying to remove it from the MTRDevice's +// collection of waiters (unlike "cancel", which does that removal). This is +// exposed so that MTRDevice can do it when invalidating. +- (void)_notifyCancellation; + @end NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index 7c6414d2a1..7f273e26f0 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -753,7 +753,6 @@ - (MTRAttributeValueWaiter *)waitForAttributeValues:(NSDictionary * currentValues = [self readAttributePaths:requestPaths]; - std::lock_guard lock(_lock); auto * attributeWaiter = [[MTRAttributeValueWaiter alloc] initWithDevice:self values:values queue:queue completion:completion]; for (MTRDeviceResponseValueDictionary currentValue in currentValues) { @@ -764,37 +763,23 @@ - (MTRAttributeValueWaiter *)waitForAttributeValues:(NSDictionary(timeout * static_cast(NSEC_PER_SEC))), DISPATCH_TIME_FOREVER, - // Allow .5 seconds of leeway; should be plenty, in practice. - static_cast(0.5 * static_cast(NSEC_PER_SEC))); - - mtr_weakify(attributeWaiter); - mtr_weakify(self); - dispatch_source_set_event_handler(timerSource, ^{ - dispatch_source_cancel(timerSource); - mtr_strongify(self); - mtr_strongify(attributeWaiter); - if (self != nil && attributeWaiter != nil) { - [self _attributeWaitTimedOut:attributeWaiter]; - } - }); - - dispatch_resume(timerSource); + [attributeWaiter _startTimerWithTimeout:timeout]; return attributeWaiter; } @@ -814,35 +799,15 @@ - (void)_attributeValue:(MTRDeviceDataValueDictionary)value reportedForPath:(MTR } for (MTRAttributeValueWaiter * attributeValueWaiter in satisfiedWaiters) { - [self _notifyAttributeValueWaiter:attributeValueWaiter withError:nil]; + [self.attributeValueWaiters removeObject:attributeValueWaiter]; + [attributeValueWaiter _notifyWithError:nil]; } } -- (void)_attributeWaitTimedOut:(MTRAttributeValueWaiter *)attributeValueWaiter +- (void)_forgetAttributeWaiter:(MTRAttributeValueWaiter *)attributeValueWaiter { std::lock_guard lock(_lock); - [self _notifyAttributeValueWaiter:attributeValueWaiter withError:[MTRError errorForCHIPErrorCode:CHIP_ERROR_TIMEOUT]]; -} - -- (void)_attributeWaitCanceled:(MTRAttributeValueWaiter *)attributeValueWaiter -{ - std::lock_guard lock(_lock); - [self _doAttributeWaitCanceled:attributeValueWaiter]; -} - -- (void)_doAttributeWaitCanceled:(MTRAttributeValueWaiter *)attributeValueWaiter -{ - os_unfair_lock_assert_owner(&_lock); - - [self _notifyAttributeValueWaiter:attributeValueWaiter withError:[MTRError errorForCHIPErrorCode:CHIP_ERROR_CANCELLED]]; -} - -- (void)_notifyAttributeValueWaiter:(MTRAttributeValueWaiter *)attributeValueWaiter withError:(NSError * _Nullable)error -{ - os_unfair_lock_assert_owner(&_lock); - [self.attributeValueWaiters removeObject:attributeValueWaiter]; - [attributeValueWaiter _notifyWithError:error]; } - (void)_cancelAllAttributeValueWaiters @@ -852,7 +817,7 @@ - (void)_cancelAllAttributeValueWaiters auto * attributeValueWaiters = self.attributeValueWaiters; self.attributeValueWaiters = nil; for (MTRAttributeValueWaiter * attributeValueWaiter in attributeValueWaiters) { - [self _doAttributeWaitCanceled:attributeValueWaiter]; + [attributeValueWaiter _notifyCancellation]; } } diff --git a/src/darwin/Framework/CHIP/MTRDevice_Internal.h b/src/darwin/Framework/CHIP/MTRDevice_Internal.h index ccd9dbebc8..8db681d480 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDevice_Internal.h @@ -176,7 +176,7 @@ MTR_DIRECT_MEMBERS // expected value for the relevant attribute. - (void)_attributeValue:(MTRDeviceDataValueDictionary)value reportedForPath:(MTRAttributePath *)path; -- (void)_attributeWaitCanceled:(MTRAttributeValueWaiter *)attributeValueWaiter; +- (void)_forgetAttributeWaiter:(MTRAttributeValueWaiter *)attributeValueWaiter; @end From e09abaec3147a9a1b6024d5a1853ec6dd135c8e3 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 19:12:07 -0800 Subject: [PATCH 011/219] Do not use reverse commissioning to pair test server (#36490) --- src/python_testing/TC_MCORE_FS_1_3.py | 95 ++++++++++----------------- 1 file changed, 35 insertions(+), 60 deletions(-) diff --git a/src/python_testing/TC_MCORE_FS_1_3.py b/src/python_testing/TC_MCORE_FS_1_3.py index 2ac1556199..4b732a1b3a 100644 --- a/src/python_testing/TC_MCORE_FS_1_3.py +++ b/src/python_testing/TC_MCORE_FS_1_3.py @@ -34,7 +34,7 @@ # --commissioning-method on-network # --discriminator 1234 # --passcode 20202021 -# --string-arg th_server_no_uid_app_path:${LIGHTING_APP_NO_UNIQUE_ID} +# --string-arg th_server_no_uid_app_path:${LIGHTING_APP_NO_UNIQUE_ID} dut_fsa_stdin_pipe:dut-fsa-stdin # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true @@ -81,6 +81,13 @@ def setup_class(self): self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) logging.info("Temporary storage directory: %s", self.storage.name) + if self.is_pics_sdk_ci_only: + # Get the named pipe path for the DUT_FSA app input from the user params. + dut_fsa_stdin_pipe = self.user_params.get("dut_fsa_stdin_pipe") + if not dut_fsa_stdin_pipe: + asserts.fail("CI setup requires --string-arg dut_fsa_stdin_pipe:") + self.dut_fsa_stdin = open(dut_fsa_stdin_pipe, "w") + self.th_server_port = 5544 self.th_server_discriminator = random.randint(0, 4095) self.th_server_passcode = 20202021 @@ -111,60 +118,6 @@ def steps_TC_MCORE_FS_1_3(self) -> list[TestStep]: "TH verifies a value is visible for the UniqueID from the DUT_FSA's Bridged Device Basic Information Cluster."), ] - async def commission_via_commissioner_control(self, controller_node_id: int, device_node_id: int, endpoint_id: int): - """Commission device_node_id to controller_node_id using CommissionerControl cluster.""" - - request_id = random.randint(0, 0xFFFFFFFFFFFFFFFF) - - vendor_id = await self.read_single_attribute_check_success( - node_id=device_node_id, - cluster=Clusters.BasicInformation, - attribute=Clusters.BasicInformation.Attributes.VendorID, - ) - - product_id = await self.read_single_attribute_check_success( - node_id=device_node_id, - cluster=Clusters.BasicInformation, - attribute=Clusters.BasicInformation.Attributes.ProductID, - ) - - await self.send_single_cmd( - node_id=controller_node_id, - endpoint=endpoint_id, - cmd=Clusters.CommissionerControl.Commands.RequestCommissioningApproval( - requestID=request_id, - vendorID=vendor_id, - productID=product_id, - ), - ) - - if not self.is_pics_sdk_ci_only: - self.wait_for_user_input("Approve Commissioning Approval Request on DUT using manufacturer specified mechanism") - - resp = await self.send_single_cmd( - node_id=controller_node_id, - endpoint=endpoint_id, - cmd=Clusters.CommissionerControl.Commands.CommissionNode( - requestID=request_id, - responseTimeoutSeconds=30, - ), - ) - - asserts.assert_equal(type(resp), Clusters.CommissionerControl.Commands.ReverseOpenCommissioningWindow, - "Incorrect response type") - - await self.send_single_cmd( - node_id=device_node_id, - cmd=Clusters.AdministratorCommissioning.Commands.OpenCommissioningWindow( - commissioningTimeout=3*60, - PAKEPasscodeVerifier=resp.PAKEPasscodeVerifier, - discriminator=resp.discriminator, - iterations=resp.iterations, - salt=resp.salt, - ), - timedRequestTimeoutMs=5000, - ) - @async_test_body async def test_TC_MCORE_FS_1_3(self): @@ -218,13 +171,35 @@ async def test_TC_MCORE_FS_1_3(self): asserts.assert_not_equal(aggregator_endpoint, 0, "Invalid aggregator endpoint. Cannot proceed with commissioning.") - await self.commission_via_commissioner_control( - controller_node_id=self.dut_node_id, - device_node_id=th_server_th_node_id, - endpoint_id=aggregator_endpoint) + # Open commissioning window on TH_SERVER_NO_UID. + discriminator = random.randint(0, 4095) + params = await self.default_controller.OpenCommissioningWindow( + nodeid=th_server_th_node_id, + option=self.default_controller.CommissioningWindowPasscode.kTokenWithRandomPin, + discriminator=discriminator, + iteration=10000, + timeout=600) + + # Commissioning TH_SERVER_NO_UID to DUT_FSA fabric. + if not self.is_pics_sdk_ci_only: + self.wait_for_user_input( + f"Commission TH_SERVER_NO_UID on DUT using manufacturer specified mechanism.\n" + f"Use the following parameters:\n" + f"- discriminator: {discriminator}\n" + f"- setupPinCode: {params.setupPinCode}\n" + f"- setupQRCode: {params.setupQRCode}\n" + f"- setupManualCode: {params.setupManualCode}\n" + f"If using FabricSync Admin, you may type:\n" + f">>> pairing onnetwork {params.setupPinCode}") + else: + self.dut_fsa_stdin.write( + f"pairing onnetwork 10 {params.setupPinCode}\n") + self.dut_fsa_stdin.flush() + # Wait for the commissioning to complete. + await asyncio.sleep(5) # Wait for the device to appear on the DUT_FSA_BRIDGE. - await asyncio.sleep(2 if self.is_pics_sdk_ci_only else 30) + await asyncio.sleep(1) # Get the list of endpoints on the DUT_FSA_BRIDGE after adding the TH_SERVER_NO_UID. dut_fsa_bridge_endpoints_new = set(await self.read_single_attribute_check_success( From 57489d1a4df3c58f99c5ef1cd8ba6256ff31cab6 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 14 Nov 2024 19:13:09 -0800 Subject: [PATCH 012/219] [Fabric-Sync] Port sync-device command from fabric-admin (#36507) --- examples/fabric-sync/admin/DeviceManager.cpp | 72 +++++++++++ examples/fabric-sync/admin/DeviceManager.h | 38 ++++++ examples/fabric-sync/admin/FabricAdmin.cpp | 21 ++++ examples/fabric-sync/admin/FabricAdmin.h | 3 + .../bridge/include/FabricAdminDelegate.h | 12 ++ examples/fabric-sync/shell/BUILD.gn | 2 + examples/fabric-sync/shell/ShellCommands.cpp | 38 +++++- .../fabric-sync/shell/SyncDeviceCommand.cpp | 112 ++++++++++++++++++ .../fabric-sync/shell/SyncDeviceCommand.h | 39 ++++++ 9 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 examples/fabric-sync/shell/SyncDeviceCommand.cpp create mode 100644 examples/fabric-sync/shell/SyncDeviceCommand.h diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 6dfdad1213..69aa0a583f 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,9 @@ namespace admin { namespace { constexpr EndpointId kAggregatorEndpointId = 1; +constexpr uint16_t kWindowTimeout = 300; +constexpr uint16_t kIteration = 1000; +constexpr uint16_t kMaxDiscriminatorLength = 4095; } // namespace @@ -75,6 +79,13 @@ void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) } } +void DeviceManager::AddSyncedDevice(const SyncedDevice & device) +{ + mSyncedDevices.insert(device); + ChipLogProgress(NotSpecified, "Added synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", + ChipLogValueX64(device.GetNodeId()), device.GetEndpointId()); +} + SyncedDevice * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) { for (auto & device : mSyncedDevices) @@ -99,6 +110,27 @@ SyncedDevice * DeviceManager::FindDeviceByNode(NodeId nodeId) return nullptr; } +void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) +{ + NodeId nodeId = scopedNodeId.GetNodeId(); + + if (bridge::FabricBridge::Instance().RemoveSynchronizedDevice(scopedNodeId) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to remove Node ID:" ChipLogFormatX64, ChipLogValueX64(nodeId)); + } + + SyncedDevice * device = FindDeviceByNode(nodeId); + if (device == nullptr) + { + ChipLogProgress(NotSpecified, "No device found with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId)); + return; + } + + mSyncedDevices.erase(*device); + ChipLogProgress(NotSpecified, "Removed synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", + ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); +} + void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) { @@ -132,6 +164,46 @@ void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint } } +void DeviceManager::OpenDeviceCommissioningWindow(ScopedNodeId scopedNodeId, uint32_t iterations, uint16_t commissioningTimeoutSec, + uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) +{ + // PairingManager isn't currently capable of OpenCommissioningWindow on a device of a fabric that it doesn't have + // the controller for. Currently no implementation need this functionality, but should they need it they will hit + // the verify or die below and it will be the responsiblity of whoever requires that functionality to implement. + VerifyOrDie(PairingManager::Instance().CurrentCommissioner().GetFabricIndex() == scopedNodeId.GetFabricIndex()); + ChipLogProgress(NotSpecified, "Opening commissioning window for Node ID: " ChipLogFormatX64, + ChipLogValueX64(scopedNodeId.GetNodeId())); + + // Open the commissioning window of a device within its own fabric. + CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow( + scopedNodeId.GetNodeId(), kRootEndpointId, commissioningTimeoutSec, iterations, discriminator, salt, verifier); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err)); + } +} + +void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpointId) +{ + // Open the commissioning window of a device from another fabric via its fabric bridge. + // This method constructs and sends a command to open the commissioning window for a device + // that is part of a different fabric, accessed through a fabric bridge. + + // Use random discriminator to have less chance of collision. + uint16_t discriminator = + Crypto::GetRandU16() % (kMaxDiscriminatorLength + 1); // Include the upper limit kMaxDiscriminatorLength + + ByteSpan emptySalt; + ByteSpan emptyVerifier; + + CHIP_ERROR err = PairingManager::Instance().OpenCommissioningWindow(mRemoteBridgeNodeId, remoteEndpointId, kWindowTimeout, + kIteration, discriminator, emptySalt, emptyVerifier); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to open commissioning window: %s", ErrorStr(err)); + } +} + CHIP_ERROR DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, uint16_t deviceRemotePort) { diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index e114a62748..9afb1eec7d 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -72,6 +72,10 @@ class DeviceManager bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; } + void AddSyncedDevice(const SyncedDevice & device); + + void RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId); + /** * @brief Determines whether a given nodeId corresponds to the remote bridge device. * @@ -97,6 +101,40 @@ class DeviceManager void OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const chip::ByteSpan & salt, const chip::ByteSpan & verifier); + /** + * @brief Open the commissioning window for a specific device within its own fabric. + * + * This function initiates the process to open the commissioning window for a device identified by the given node ID. + * + * @param scopedNodeId The scoped node ID of the device that should open the commissioning window. + * @param iterations The number of PBKDF (Password-Based Key Derivation Function) iterations to use + * for deriving the PAKE (Password Authenticated Key Exchange) verifier. + * @param commissioningTimeoutSec The time in seconds before the commissioning window closes. This value determines + * how long the commissioning window remains open for incoming connections. + * @param discriminator The device-specific discriminator, determined during commissioning, which helps + * to uniquely identify the device among others. + * @param salt The salt used in the cryptographic operations for commissioning. + * @param verifier The PAKE verifier used to authenticate the commissioning process. + * + */ + void OpenDeviceCommissioningWindow(chip::ScopedNodeId scopedNodeId, uint32_t iterations, uint16_t commissioningTimeoutSec, + uint16_t discriminator, const chip::ByteSpan & salt, const chip::ByteSpan & verifier); + + /** + * @brief Open the commissioning window of a device from another fabric via its fabric bridge. + * + * This function initiates the process to open the commissioning window for a device that belongs to another + * fabric, accessed through a fabric bridge. + * + * @param remoteEndpointId The endpoint ID of the remote device that should open the commissioning window. + * This endpoint is associated with the device in the other fabric, accessed via the + * fabric bridge. + * + * @note This function is used when the device to be commissioned is part of a different fabric and must be + * accessed through an intermediary fabric bridge. + */ + void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); + /** * @brief Pair a remote fabric bridge with a given node ID. * diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 65b5a5a8e8..4e170ce78d 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -38,6 +38,27 @@ FabricAdmin & FabricAdmin::Instance() return sInstance; } +CHIP_ERROR FabricAdmin::OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams params, FabricIndex fabricIndex) +{ + ScopedNodeId scopedNodeId(params.GetNodeId(), fabricIndex); + uint32_t iterations = params.GetIteration(); + uint16_t discriminator = params.GetDiscriminator(); + uint16_t commissioningTimeoutSec = static_cast(params.GetTimeout().count()); + + // Log request details for debugging purposes + ChipLogProgress(NotSpecified, + "Received OpenCommissioningWindow request: NodeId " ChipLogFormatX64 + ", Timeout: %u, Iterations: %u, Discriminator: %u", + ChipLogValueX64(scopedNodeId.GetNodeId()), commissioningTimeoutSec, iterations, discriminator); + + // Open the device commissioning window with provided salt and verifier data + DeviceManager::Instance().OpenDeviceCommissioningWindow(scopedNodeId, iterations, commissioningTimeoutSec, discriminator, + ByteSpan(params.GetSalt().data(), params.GetSalt().size()), + ByteSpan(params.GetVerifier().data(), params.GetVerifier().size())); + + return CHIP_NO_ERROR; +} + CHIP_ERROR FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParams params, VendorId vendorId, uint16_t productId) { diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h index 1219e594fa..bec98dc414 100644 --- a/examples/fabric-sync/admin/FabricAdmin.h +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -42,6 +42,9 @@ class FabricAdmin final : public bridge::FabricAdminDelegate public: static FabricAdmin & Instance(); + CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, + chip::FabricIndex fabricIndex) override; + CHIP_ERROR CommissionRemoteBridge(chip::Controller::CommissioningWindowPasscodeParams params, chip::VendorId vendorId, uint16_t productId) override; diff --git a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h index 8b67ffd5b2..1637c5294f 100644 --- a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h +++ b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h @@ -30,6 +30,18 @@ class FabricAdminDelegate public: virtual ~FabricAdminDelegate() = default; + /** + * Opens a commissioning window for a specified node using pre-computed PAKE passcode verifier. + * + * @param params Params for opening the commissioning window using verifier. + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully sent. + * - CHIP_ERROR_BUSY: Another commissioning window is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred. + */ + virtual CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, + chip::FabricIndex fabricIndex) = 0; + /** * Reverse commission a bridge using the specified parameters. * diff --git a/examples/fabric-sync/shell/BUILD.gn b/examples/fabric-sync/shell/BUILD.gn index 436f8b5160..3aa5612225 100644 --- a/examples/fabric-sync/shell/BUILD.gn +++ b/examples/fabric-sync/shell/BUILD.gn @@ -39,6 +39,8 @@ source_set("shell") { "RemoveDeviceCommand.h", "ShellCommands.cpp", "ShellCommands.h", + "SyncDeviceCommand.cpp", + "SyncDeviceCommand.h", ] deps = [ diff --git a/examples/fabric-sync/shell/ShellCommands.cpp b/examples/fabric-sync/shell/ShellCommands.cpp index 3bab442aa5..4923823481 100644 --- a/examples/fabric-sync/shell/ShellCommands.cpp +++ b/examples/fabric-sync/shell/ShellCommands.cpp @@ -19,6 +19,7 @@ #include "AddDeviceCommand.h" #include "RemoveBridgeCommand.h" #include "RemoveDeviceCommand.h" +#include "SyncDeviceCommand.h" #include #include @@ -129,11 +130,11 @@ static CHIP_ERROR HandleAddDeviceCommand(int argc, char ** argv) // Parse arguments chip::NodeId nodeId = static_cast(strtoull(argv[1], nullptr, 10)); - uint32_t setupPINCode = static_cast(strtoul(argv[2], nullptr, 10)); + uint32_t payload = static_cast(strtoul(argv[2], nullptr, 10)); const char * remoteAddr = argv[3]; uint16_t remotePort = static_cast(strtoul(argv[4], nullptr, 10)); - auto command = std::make_unique(nodeId, setupPINCode, remoteAddr, remotePort); + auto command = std::make_unique(nodeId, payload, remoteAddr, remotePort); CHIP_ERROR result = command->RunCommand(); if (result == CHIP_NO_ERROR) @@ -173,6 +174,35 @@ static CHIP_ERROR HandleRemoveDeviceCommand(int argc, char ** argv) return result; } +static CHIP_ERROR HandleSyncDeviceCommand(int argc, char ** argv) +{ + if (argc != 2) + { + fprintf(stderr, "Invalid arguments. Usage: app sync-device\n"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Check if there is already an active command + if (commands::CommandRegistry::Instance().IsCommandActive()) + { + fprintf(stderr, "Another command is currently active. Please wait until it completes.\n"); + return CHIP_ERROR_BUSY; + } + + // Parse arguments + chip::EndpointId endpointId = static_cast(strtoul(argv[1], nullptr, 10)); + + auto command = std::make_unique(endpointId); + + CHIP_ERROR result = command->RunCommand(); + if (result == CHIP_NO_ERROR) + { + commands::CommandRegistry::Instance().SetActiveCommand(std::move(command)); + } + + return result; +} + static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) { CHIP_ERROR error = CHIP_NO_ERROR; @@ -201,6 +231,10 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) { return HandleRemoveDeviceCommand(argc, argv); } + else if (strcmp(argv[0], "sync-device") == 0) + { + return HandleSyncDeviceCommand(argc, argv); + } else { return CHIP_ERROR_INVALID_ARGUMENT; diff --git a/examples/fabric-sync/shell/SyncDeviceCommand.cpp b/examples/fabric-sync/shell/SyncDeviceCommand.cpp new file mode 100644 index 0000000000..871c8d68fe --- /dev/null +++ b/examples/fabric-sync/shell/SyncDeviceCommand.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "SyncDeviceCommand.h" + +#include +#include +#include + +using namespace ::chip; + +namespace { + +// Constants +constexpr uint32_t kCommissionPrepareTimeMs = 500; + +} // namespace + +namespace commands { + +SyncDeviceCommand::SyncDeviceCommand(EndpointId remoteEndpointId) : mRemoteEndpointId(remoteEndpointId) {} + +void SyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, SetupPayload payload) +{ + ChipLogProgress(NotSpecified, "FabricSyncDeviceCommand::OnCommissioningWindowOpened"); + + if (err == CHIP_NO_ERROR) + { + char payloadBuffer[admin::kMaxManualCodeLength + 1]; + MutableCharSpan manualCode(payloadBuffer); + CHIP_ERROR error = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualCode); + if (error == CHIP_NO_ERROR) + { + NodeId nodeId = admin::DeviceManager::Instance().GetNextAvailableNodeId(); + + admin::PairingManager::Instance().SetPairingDelegate(this); + mAssignedNodeId = nodeId; + + usleep(kCommissionPrepareTimeMs * 1000); + + admin::DeviceManager::Instance().PairRemoteDevice(nodeId, payloadBuffer); + } + else + { + ChipLogError(NotSpecified, "Unable to generate manual code for setup payload: %" CHIP_ERROR_FORMAT, error.Format()); + } + } + else + { + ChipLogError(NotSpecified, + "Failed to open synced device (0x:" ChipLogFormatX64 ") commissioning window: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } +} + +void SyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mAssignedNodeId != deviceId) + { + // Ignore if the deviceId does not match the mAssignedNodeId. + // This scenario should not occur because no other device should be commissioned during the fabric sync process. + return; + } + + if (err == CHIP_NO_ERROR) + { + admin::DeviceManager::Instance().AddSyncedDevice(admin::SyncedDevice(mAssignedNodeId, mRemoteEndpointId)); + } + else + { + ChipLogError(NotSpecified, "Failed to pair synced device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + CommandRegistry::Instance().ResetActiveCommand(); +} + +CHIP_ERROR SyncDeviceCommand::RunCommand() +{ + if (!admin::DeviceManager::Instance().IsFabricSyncReady()) + { + // print to console + Shell::streamer_t * sout = Shell::streamer_get(); + Shell::streamer_printf(sout, "Remote Fabric Bridge has already been configured.\n"); + + return CHIP_ERROR_INCORRECT_STATE; + } + + ChipLogProgress(NotSpecified, "Running SyncDeviceCommand with EndpointId: %u", mRemoteEndpointId); + + admin::PairingManager::Instance().SetOpenCommissioningWindowDelegate(this); + admin::DeviceManager::Instance().OpenRemoteDeviceCommissioningWindow(mRemoteEndpointId); + + return CHIP_NO_ERROR; +} + +} // namespace commands diff --git a/examples/fabric-sync/shell/SyncDeviceCommand.h b/examples/fabric-sync/shell/SyncDeviceCommand.h new file mode 100644 index 0000000000..270f57d889 --- /dev/null +++ b/examples/fabric-sync/shell/SyncDeviceCommand.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include +#include + +namespace commands { + +class SyncDeviceCommand : public Command, public admin::CommissioningWindowDelegate, public admin::PairingDelegate +{ +public: + SyncDeviceCommand(chip::EndpointId remoteEndpointId); + void OnCommissioningWindowOpened(chip::NodeId deviceId, CHIP_ERROR status, chip::SetupPayload payload) override; + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; + CHIP_ERROR RunCommand() override; + +private: + chip::EndpointId mRemoteEndpointId = chip::kInvalidEndpointId; + chip::NodeId mAssignedNodeId = chip::kUndefinedNodeId; +}; + +} // namespace commands From c0dbaaffd0a93bdf73942b91aadff9b263c4567e Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Fri, 15 Nov 2024 07:30:54 -0500 Subject: [PATCH 013/219] fan_control_server: Fix circular callback issue (#36489) * fan_control_server: Fix circular callback issue This PR fixes a circular callback bug in fan control server using flags when updating SpeedSetting and PercentSetting. Before this change, a PercentSetting write to 25% would end up circling back to 30% as shown: ``` [MatterTest] 11-12 19:16:40.792 INFO @@@ WRITE PercentSetting to 25 [MatterTest] 11-12 19:16:40.801 INFO @@@ ATTRIB: EP1/FanControl/SpeedSetting: 3 [MatterTest] 11-12 19:16:40.802 INFO @@@ ATTRIB: EP1/FanControl/SpeedCurrent: 3 [MatterTest] 11-12 19:16:40.802 INFO @@@ ATTRIB: EP1/FanControl/PercentSetting: 30 [MatterTest] 11-12 19:16:40.802 INFO @@@ ATTRIB: EP1/FanControl/PercentCurrent: 30 ``` Now it behaves as expected: ``` [MatterTest] 11-13 18:54:27.961 INFO @@@ WRITE PercentSetting to 25 [MatterTest] 11-13 18:54:27.970 INFO @@@ ATTRIB: EP1/FanControl/SpeedSetting: 3 [MatterTest] 11-13 18:54:27.970 INFO @@@ ATTRIB: EP1/FanControl/SpeedCurrent: 3 [MatterTest] 11-13 18:54:27.970 INFO @@@ ATTRIB: EP1/FanControl/PercentSetting: 25 [MatterTest] 11-13 18:54:27.971 INFO @@@ ATTRIB: EP1/FanControl/PercentCurrent: 25 ``` Co-authored-by: lpbeliveau-silabs * Addressed review suggestions --------- Co-authored-by: lpbeliveau-silabs --- .../fan-control-server/fan-control-server.cpp | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 46f4c6d7c0..7ece1a1b57 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,10 @@ namespace { // Indicates if the write operation is from the cluster server itself bool gWriteFromClusterLogic = false; +// Avoid circular callback calls when adjusting SpeedSetting and PercentSetting together. +ScopedChangeOnly gSpeedWriteInProgress(false); +ScopedChangeOnly gPercentWriteInProgress(false); + Status SetFanModeToOff(EndpointId endpointId) { FanModeEnum currentFanMode; @@ -185,6 +190,10 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute break; } case SpeedSetting::Id: { + if (gSpeedWriteInProgress) + { + return Status::WriteIgnored; + } if (SupportsMultiSpeed(attributePath.mEndpointId)) { // Check if the SpeedSetting is null. @@ -224,6 +233,10 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute break; } case PercentSetting::Id: { + if (gPercentWriteInProgress) + { + return Status::WriteIgnored; + } // Check if the PercentSetting is null. if (NumericAttributeTraits::IsNullValue(*value)) { @@ -362,12 +375,18 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt DataModel::Nullable percentSetting; Status status = PercentSetting::Get(attributePath.mEndpointId, percentSetting); VerifyOrReturn(Status::Success == status && !percentSetting.IsNull()); + uint8_t speedMax; + status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); + VerifyOrReturn(Status::Success == status, + ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); + // Avoid circular callback calls + ScopedChange PercentWriteInProgress(gPercentWriteInProgress, true); // If PercentSetting is set to 0, the server SHALL set the FanMode attribute value to Off. if (percentSetting.Value() == 0) { status = SetFanModeToOff(attributePath.mEndpointId); - VerifyOrReturn(Status::Success == status, + VerifyOrReturn(status == Status::Success, ChipLogError(Zcl, "Failed to set FanMode to off with error: 0x%02x", to_underlying(status))); } @@ -375,26 +394,13 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt { // Adjust SpeedSetting from a percent value change for PercentSetting // speed = ceil( SpeedMax * (percent * 0.01) ) - uint8_t speedMax; - status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); - - DataModel::Nullable currentSpeedSetting; - status = SpeedSetting::Get(attributePath.mEndpointId, currentSpeedSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get SpeedSetting with error: 0x%02x", to_underlying(status))); - uint16_t percent = percentSetting.Value(); // Plus 99 then integer divide by 100 instead of multiplying 0.01 to avoid floating point precision error uint8_t speedSetting = static_cast((speedMax * percent + 99) / 100); - if (currentSpeedSetting.IsNull() || speedSetting != currentSpeedSetting.Value()) - { - status = SpeedSetting::Set(attributePath.mEndpointId, speedSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to set SpeedSetting with error: 0x%02x", to_underlying(status))); - } + status = SpeedSetting::Set(attributePath.mEndpointId, speedSetting); + VerifyOrDo(Status::Success == status, + ChipLogError(Zcl, "Failed to set SpeedSetting with error: 0x%02x", to_underlying(status))); } break; } @@ -404,7 +410,13 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt DataModel::Nullable speedSetting; Status status = SpeedSetting::Get(attributePath.mEndpointId, speedSetting); VerifyOrReturn(Status::Success == status && !speedSetting.IsNull()); + uint8_t speedMax; + status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); + VerifyOrReturn(Status::Success == status, + ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); + // Avoid circular callback calls + ScopedChange SpeedWriteInProgress(gSpeedWriteInProgress, true); // If SpeedSetting is set to 0, the server SHALL set the FanMode attribute value to Off. if (speedSetting.Value() == 0) { @@ -415,25 +427,12 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt // Adjust PercentSetting from a speed value change for SpeedSetting // percent = floor( speed/SpeedMax * 100 ) - uint8_t speedMax; - status = SpeedMax::Get(attributePath.mEndpointId, &speedMax); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get SpeedMax with error: 0x%02x", to_underlying(status))); - - DataModel::Nullable currentPercentSetting; - status = PercentSetting::Get(attributePath.mEndpointId, currentPercentSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to get PercentSetting with error: 0x%02x", to_underlying(status))); - float speed = speedSetting.Value(); Percent percentSetting = static_cast(speed / speedMax * 100); - if (currentPercentSetting.IsNull() || percentSetting != currentPercentSetting.Value()) - { - status = PercentSetting::Set(attributePath.mEndpointId, percentSetting); - VerifyOrReturn(Status::Success == status, - ChipLogError(Zcl, "Failed to set PercentSetting with error: 0x%02x", to_underlying(status))); - } + status = PercentSetting::Set(attributePath.mEndpointId, percentSetting); + VerifyOrDo(Status::Success == status, + ChipLogError(Zcl, "Failed to set PercentSetting with error: 0x%02x", to_underlying(status))); } break; } From 503c9d0b10051c4412d48479070bd572add51cad Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Fri, 15 Nov 2024 14:36:07 +0200 Subject: [PATCH 014/219] [Telink] fix stack sizes to avoid 90% usage (#36485) * [Telink] Add temporarry THREAD_ANALYZER to check stack sizes during crash * [Telink] fix configs * [Telink] Increase OpenThread stack (98% usage during OTA) * [Telink] Set INFO as default MCUboot log level * [Telink] define CHIP_TASK_STACK_SIZE from one place * [Telink] Add thread-analyzer as target build * [Telink] decrise BOOT_MAX_IMG_SECTORS * [Telink] temporary enable THREAD_ANALYZER by default * [Telink] Increase stack sizes to avoid 90+% usage * [Telink] increase more * [Telink] set THREAD_ANALYZER=n by default --- config/telink/app/bootloader.conf | 5 ++-- config/telink/chip-module/Kconfig | 1 + config/telink/chip-module/Kconfig.defaults | 25 ++++++++++++++----- scripts/build/build/targets.py | 1 + scripts/build/builders/telink.py | 5 ++++ .../build/testdata/all_targets_linux_x64.txt | 2 +- 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/config/telink/app/bootloader.conf b/config/telink/app/bootloader.conf index 52937e1649..0ffacc8c0b 100644 --- a/config/telink/app/bootloader.conf +++ b/config/telink/app/bootloader.conf @@ -30,7 +30,8 @@ CONFIG_BOOT_SWAP_USING_SCRATCH=n CONFIG_BOOT_VALIDATE_SLOT0=y # Maximum number of image sectors supported by the bootloader. -CONFIG_BOOT_MAX_IMG_SECTORS=4096 +# Maximum signed image size: 512 * 4096 = 2M Bytes +CONFIG_BOOT_MAX_IMG_SECTORS=512 # Sets log level for modules which don't specify it explicitly. # When set to 0 it means log will not be activated for those modules. @@ -40,4 +41,4 @@ CONFIG_BOOT_MAX_IMG_SECTORS=4096 # - 2 WARNING, default to write LOG_LEVEL_WRN # - 3 INFO, default to write LOG_LEVEL_INFO # - 4 DEBUG, default to write LOG_LEVEL_DBG -CONFIG_LOG_DEFAULT_LEVEL=1 +CONFIG_LOG_DEFAULT_LEVEL=3 diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index ee87af2bbe..b06c7c8559 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -246,6 +246,7 @@ config CHIP_ENABLE_POWER_ON_FACTORY_RESET config CHIP_TASK_STACK_SIZE int + default 4864 if PM default 8192 config CHIP_USE_MARS_SENSOR diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index d28d77d6cf..bb722e8a3a 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -71,7 +71,7 @@ config IDLE_STACK_SIZE default 512 if PM config ISR_STACK_SIZE - default 502 if PM + default 576 if PM config SYSTEM_WORKQUEUE_STACK_SIZE default 616 if PM @@ -154,7 +154,7 @@ config BT_DEVICE_NAME_GATT_WRITABLE default n config B9X_BLE_CTRL_THREAD_STACK_SIZE - default 576 + default 648 config B9X_BLE_CTRL_MASTER_MAX_NUM default 0 @@ -261,10 +261,10 @@ config CHIP_ENABLE_ICD_SUPPORT default y if CHIP_THREAD_DEVICE_ROLE_SLEEPY_END_DEVICE config OPENTHREAD_THREAD_STACK_SIZE - default 2178 if PM + default 2400 if PM config OPENTHREAD_RADIO_WORKQUEUE_STACK_SIZE - default 361 if PM + default 432 if PM default 608 config OPENTHREAD_SLAAC @@ -366,6 +366,9 @@ config CHIP_WIFI_CONNECTION_RECOVERY_JITTER a random jitter interval is added to it to avoid periodicity. The random jitter is selected within range [-JITTER; +JITTER]. +config NET_MGMT_EVENT_STACK_SIZE + default 1128 + endif # CHIP_WIFI config CHIP_ENABLE_PAIRING_AUTOSTART @@ -448,7 +451,17 @@ config PWM_SHELL config OPENTHREAD_SHELL default n -config CHIP_TASK_STACK_SIZE - default 4864 if PM +# Thread analyzer +config THREAD_ANALYZER + default n + select THREAD_ANALYZER_AUTO + +config THREAD_ANALYZER_AUTO_INTERVAL + default 5 + depends on THREAD_ANALYZER_AUTO + +config THREAD_ANALYZER_LOG_LEVEL + default 3 # info + depends on THREAD_ANALYZER endif diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index b36824bc48..0f80756ec4 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -801,6 +801,7 @@ def BuildTelinkTarget(): target.AppendModifier('mars', mars_board_config=True) target.AppendModifier('usb', usb_board_config=True) target.AppendModifier('compress-lzma', compress_lzma_config=True) + target.AppendModifier('thread-analyzer', thread_analyzer_config=True) return target diff --git a/scripts/build/builders/telink.py b/scripts/build/builders/telink.py index 644f4cdc08..a494300716 100644 --- a/scripts/build/builders/telink.py +++ b/scripts/build/builders/telink.py @@ -155,6 +155,7 @@ def __init__(self, mars_board_config: bool = False, usb_board_config: bool = False, compress_lzma_config: bool = False, + thread_analyzer_config: bool = False, ): super(TelinkBuilder, self).__init__(root, runner) self.app = app @@ -168,6 +169,7 @@ def __init__(self, self.mars_board_config = mars_board_config self.usb_board_config = usb_board_config self.compress_lzma_config = compress_lzma_config + self.thread_analyzer_config = thread_analyzer_config def get_cmd_prefixes(self): if not self._runner.dry_run: @@ -215,6 +217,9 @@ def generate(self): if self.compress_lzma_config: flags.append("-DCONFIG_COMPRESS_LZMA=y") + if self.thread_analyzer_config: + flags.append("-DCONFIG_THREAD_ANALYZER=y") + if self.options.pregen_dir: flags.append(f"-DCHIP_CODEGEN_PREGEN_DIR={shlex.quote(self.options.pregen_dir)}") diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index f34f42b55e..c473de1aa1 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -22,5 +22,5 @@ nuttx-x64-light qpg-qpg6105-{lock,light,shell,persistent-storage,light-switch,thermostat}[-updateimage] stm32-stm32wb5mm-dk-light tizen-arm-{all-clusters,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-coverage][-with-ui] -telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma] +telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma][-thread-analyzer] openiotsdk-{shell,lock}[-mbedtls][-psa] From e019c0f3dc7e8a974d70ef02ce723075b379dcb0 Mon Sep 17 00:00:00 2001 From: dinabenamar <108664279+dinabenamar@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:58:28 +0100 Subject: [PATCH 015/219] [NXP][platform][common] Remove unrequired config defines to use default values instead (#36497) Signed-off-by: Dina Benamar --- src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h index 1cdb064459..5d8825bc8a 100644 --- a/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h +++ b/src/platform/nxp/common/CHIPDeviceNXPPlatformDefaultConfig.h @@ -38,9 +38,6 @@ #define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING CONFIG_CHIP_DEVICE_SOFTWARE_VERSION_STRING #define CHIP_DEVICE_CONFIG_TEST_MANUFACTURING_DATE CONFIG_CHIP_DEVICE_MANUFACTURING_DATE #define CHIP_DEVICE_CONFIG_DEVICE_TYPE CONFIG_CHIP_DEVICE_TYPE -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT CONFIG_CHIP_DEVICE_SPAKE2_IT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT CONFIG_CHIP_DEVICE_SPAKE2_SALT -#define CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER CONFIG_CHIP_DEVICE_SPAKE2_TEST_VERIFIER #if !CONFIG_CHIP_PLAT_LOAD_REAL_FACTORY_DATA #define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR CONFIG_CHIP_DEVICE_DISCRIMINATOR From 9c505b3888b702f2b62a0a068e4efde8959bbe82 Mon Sep 17 00:00:00 2001 From: Mihai Ignat <50373067+mihai-ignat@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:17:28 +0200 Subject: [PATCH 016/219] [nxp][examples][rt1060] Update WiFi credentials setting in RT1060 readme (#36496) --- examples/all-clusters-app/nxp/rt/rt1060/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/all-clusters-app/nxp/rt/rt1060/README.md b/examples/all-clusters-app/nxp/rt/rt1060/README.md index 96822ff6eb..3ddcbd7c85 100644 --- a/examples/all-clusters-app/nxp/rt/rt1060/README.md +++ b/examples/all-clusters-app/nxp/rt/rt1060/README.md @@ -310,7 +310,7 @@ user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt106 build-time which will enable the device to join the Wi-Fi AP at startup): ``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_config_network_layer_ble=false tcp_download=true wifi_ssid=\"your_wifi_ssid\" wifi_password=\"your_wifi_password\"" out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true iwx12_transceiver=true evkname=\"evkcmimxrt1060\" chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\"" out/debug user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug ``` @@ -400,7 +400,7 @@ user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt106 - Build Matter with Border Router configuration with onnetwork commissioning: ``` -user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ gn gen --args="chip_enable_wifi=true w8801_transceiver=true nxp_enable_matter_cli=true chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"your_wifi_ssid\" wifi_auto_connect_at_boot_password=\"your_wifi_password\" chip_enable_openthread=true k32w0_transceiver=true k32w0_transceiver_bin_path=\"/path/to/ot-rcp/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\"" out/debug +user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ export ssid_name= && export ssid_password= && gn gen --args="chip_enable_wifi=true w8801_transceiver=true nxp_enable_matter_cli=true chip_config_network_layer_ble=false wifi_auto_connect_at_boot=true wifi_auto_connect_at_boot_ssid=\"${ssid_name}\" wifi_auto_connect_at_boot_password=\"${ssid_password}\" chip_enable_openthread=true k32w0_transceiver=true k32w0_transceiver_bin_path=\"/path/to/ot-rcp/ot-rcp-ble-hci-bb-k32w061.elf.bin.h\"" out/debug user@ubuntu:~/Desktop/git/connectedhomeip/examples/all-clusters-app/nxp/rt/rt1060$ ninja -C out/debug ``` From 144269a2ed0f6d40fb06423b019d875b1e23d0d9 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Fri, 15 Nov 2024 10:25:21 -0500 Subject: [PATCH 017/219] Add missing #include for size_t (#36474) --- src/lib/support/FunctionTraits.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/support/FunctionTraits.h b/src/lib/support/FunctionTraits.h index 17853a50af..17f02e983a 100644 --- a/src/lib/support/FunctionTraits.h +++ b/src/lib/support/FunctionTraits.h @@ -17,6 +17,7 @@ #pragma once +#include #include namespace chip { From 636abc30bad1f7fe11fab5270346f5091f0511d8 Mon Sep 17 00:00:00 2001 From: Erwin Pan Date: Fri, 15 Nov 2024 15:25:40 +0000 Subject: [PATCH 018/219] [Chef] add Multi-sensor (#36469) * Chef add multi sensor * Fix compilation issues * Remove Groups cluster,fix by TC_DeviceConformance.py --- ...ualitysensor_powersource_367e7cea91.matter | 3142 ++++++ ...irqualitysensor_powersource_367e7cea91.zap | 9272 +++++++++++++++++ 2 files changed, 12414 insertions(+) create mode 100644 examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter create mode 100644 examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap diff --git a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter new file mode 100644 index 0000000000..27c88b4fb8 --- /dev/null +++ b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.matter @@ -0,0 +1,3142 @@ +// This IDL was generated automatically by ZAP. +// It is for view/code review purposes only. + +enum AreaTypeTag : enum8 { + kAisle = 0; + kAttic = 1; + kBackDoor = 2; + kBackYard = 3; + kBalcony = 4; + kBallroom = 5; + kBathroom = 6; + kBedroom = 7; + kBorder = 8; + kBoxroom = 9; + kBreakfastRoom = 10; + kCarport = 11; + kCellar = 12; + kCloakroom = 13; + kCloset = 14; + kConservatory = 15; + kCorridor = 16; + kCraftRoom = 17; + kCupboard = 18; + kDeck = 19; + kDen = 20; + kDining = 21; + kDrawingRoom = 22; + kDressingRoom = 23; + kDriveway = 24; + kElevator = 25; + kEnsuite = 26; + kEntrance = 27; + kEntryway = 28; + kFamilyRoom = 29; + kFoyer = 30; + kFrontDoor = 31; + kFrontYard = 32; + kGameRoom = 33; + kGarage = 34; + kGarageDoor = 35; + kGarden = 36; + kGardenDoor = 37; + kGuestBathroom = 38; + kGuestBedroom = 39; + kGuestRestroom = 40; + kGuestRoom = 41; + kGym = 42; + kHallway = 43; + kHearthRoom = 44; + kKidsRoom = 45; + kKidsBedroom = 46; + kKitchen = 47; + kLarder = 48; + kLaundryRoom = 49; + kLawn = 50; + kLibrary = 51; + kLivingRoom = 52; + kLounge = 53; + kMediaTVRoom = 54; + kMudRoom = 55; + kMusicRoom = 56; + kNursery = 57; + kOffice = 58; + kOutdoorKitchen = 59; + kOutside = 60; + kPantry = 61; + kParkingLot = 62; + kParlor = 63; + kPatio = 64; + kPlayRoom = 65; + kPoolRoom = 66; + kPorch = 67; + kPrimaryBathroom = 68; + kPrimaryBedroom = 69; + kRamp = 70; + kReceptionRoom = 71; + kRecreationRoom = 72; + kRestroom = 73; + kRoof = 74; + kSauna = 75; + kScullery = 76; + kSewingRoom = 77; + kShed = 78; + kSideDoor = 79; + kSideYard = 80; + kSittingRoom = 81; + kSnug = 82; + kSpa = 83; + kStaircase = 84; + kSteamRoom = 85; + kStorageRoom = 86; + kStudio = 87; + kStudy = 88; + kSunRoom = 89; + kSwimmingPool = 90; + kTerrace = 91; + kUtilityRoom = 92; + kWard = 93; + kWorkshop = 94; +} + +enum AtomicRequestTypeEnum : enum8 { + kBeginWrite = 0; + kCommitWrite = 1; + kRollbackWrite = 2; +} + +enum FloorSurfaceTag : enum8 { + kCarpet = 0; + kCeramic = 1; + kConcrete = 2; + kCork = 3; + kDeepCarpet = 4; + kDirt = 5; + kEngineeredWood = 6; + kGlass = 7; + kGrass = 8; + kHardwood = 9; + kLaminate = 10; + kLinoleum = 11; + kMat = 12; + kMetal = 13; + kPlastic = 14; + kPolishedConcrete = 15; + kRubber = 16; + kRug = 17; + kSand = 18; + kStone = 19; + kTatami = 20; + kTerrazzo = 21; + kTile = 22; + kVinyl = 23; +} + +enum LandmarkTag : enum8 { + kAirConditioner = 0; + kAirPurifier = 1; + kBackDoor = 2; + kBarStool = 3; + kBathMat = 4; + kBathtub = 5; + kBed = 6; + kBookshelf = 7; + kChair = 8; + kChristmasTree = 9; + kCoatRack = 10; + kCoffeeTable = 11; + kCookingRange = 12; + kCouch = 13; + kCountertop = 14; + kCradle = 15; + kCrib = 16; + kDesk = 17; + kDiningTable = 18; + kDishwasher = 19; + kDoor = 20; + kDresser = 21; + kLaundryDryer = 22; + kFan = 23; + kFireplace = 24; + kFreezer = 25; + kFrontDoor = 26; + kHighChair = 27; + kKitchenIsland = 28; + kLamp = 29; + kLitterBox = 30; + kMirror = 31; + kNightstand = 32; + kOven = 33; + kPetBed = 34; + kPetBowl = 35; + kPetCrate = 36; + kRefrigerator = 37; + kScratchingPost = 38; + kShoeRack = 39; + kShower = 40; + kSideDoor = 41; + kSink = 42; + kSofa = 43; + kStove = 44; + kTable = 45; + kToilet = 46; + kTrashCan = 47; + kLaundryWasher = 48; + kWindow = 49; + kWineCooler = 50; +} + +enum PositionTag : enum8 { + kLeft = 0; + kRight = 1; + kTop = 2; + kBottom = 3; + kMiddle = 4; + kRow = 5; + kColumn = 6; +} + +enum RelativePositionTag : enum8 { + kUnder = 0; + kNextTo = 1; + kAround = 2; + kOn = 3; + kAbove = 4; + kFrontOf = 5; + kBehind = 6; +} + +enum TestGlobalEnum : enum8 { + kSomeValue = 0; + kSomeOtherValue = 1; + kFinalValue = 2; +} + +enum ThreeLevelAutoEnum : enum8 { + kLow = 0; + kMedium = 1; + kHigh = 2; + kAutomatic = 3; +} + +bitmap TestGlobalBitmap : bitmap32 { + kFirstBit = 0x1; + kSecondBit = 0x2; +} + +struct TestGlobalStruct { + char_string<128> name = 0; + nullable TestGlobalBitmap myBitmap = 1; + optional nullable TestGlobalEnum myEnum = 2; +} + +struct LocationDescriptorStruct { + char_string<128> locationName = 0; + nullable int16s floorNumber = 1; + nullable AreaTypeTag areaType = 2; +} + +struct AtomicAttributeStatusStruct { + attrib_id attributeID = 0; + status statusCode = 1; +} + +/** Attributes and commands for putting a device into Identification mode (e.g. flashing a light). */ +cluster Identify = 3 { + revision 4; + + enum EffectIdentifierEnum : enum8 { + kBlink = 0; + kBreathe = 1; + kOkay = 2; + kChannelChange = 11; + kFinishEffect = 254; + kStopEffect = 255; + } + + enum EffectVariantEnum : enum8 { + kDefault = 0; + } + + enum IdentifyTypeEnum : enum8 { + kNone = 0; + kLightOutput = 1; + kVisibleIndicator = 2; + kAudibleBeep = 3; + kDisplay = 4; + kActuator = 5; + } + + attribute int16u identifyTime = 0; + readonly attribute IdentifyTypeEnum identifyType = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct IdentifyRequest { + int16u identifyTime = 0; + } + + request struct TriggerEffectRequest { + EffectIdentifierEnum effectIdentifier = 0; + EffectVariantEnum effectVariant = 1; + } + + /** Command description for Identify */ + command access(invoke: manage) Identify(IdentifyRequest): DefaultSuccess = 0; + /** Command description for TriggerEffect */ + command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; +} + +/** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ +cluster Descriptor = 29 { + revision 2; + + bitmap Feature : bitmap32 { + kTagList = 0x1; + } + + struct DeviceTypeStruct { + devtype_id deviceType = 0; + int16u revision = 1; + } + + struct SemanticTagStruct { + nullable vendor_id mfgCode = 0; + enum8 namespaceID = 1; + enum8 tag = 2; + optional nullable char_string label = 3; + } + + readonly attribute DeviceTypeStruct deviceTypeList[] = 0; + readonly attribute cluster_id serverList[] = 1; + readonly attribute cluster_id clientList[] = 2; + readonly attribute endpoint_no partsList[] = 3; + readonly attribute optional SemanticTagStruct tagList[] = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ +cluster Binding = 30 { + revision 1; // NOTE: Default/not specifically set + + fabric_scoped struct TargetStruct { + optional node_id node = 1; + optional group_id group = 2; + optional endpoint_no endpoint = 3; + optional cluster_id cluster = 4; + fabric_idx fabricIndex = 254; + } + + attribute access(write: manage) TargetStruct binding[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The Access Control Cluster exposes a data model view of a + Node's Access Control List (ACL), which codifies the rules used to manage + and enforce Access Control for the Node's endpoints and their associated + cluster instances. */ +cluster AccessControl = 31 { + revision 2; + + enum AccessControlEntryAuthModeEnum : enum8 { + kPASE = 1; + kCASE = 2; + kGroup = 3; + } + + enum AccessControlEntryPrivilegeEnum : enum8 { + kView = 1; + kProxyView = 2; + kOperate = 3; + kManage = 4; + kAdminister = 5; + } + + enum AccessRestrictionTypeEnum : enum8 { + kAttributeAccessForbidden = 0; + kAttributeWriteForbidden = 1; + kCommandForbidden = 2; + kEventForbidden = 3; + } + + enum ChangeTypeEnum : enum8 { + kChanged = 0; + kAdded = 1; + kRemoved = 2; + } + + bitmap Feature : bitmap32 { + kExtension = 0x1; + kManagedDevice = 0x2; + } + + struct AccessRestrictionStruct { + AccessRestrictionTypeEnum type = 0; + nullable int32u id = 1; + } + + struct CommissioningAccessRestrictionEntryStruct { + endpoint_no endpoint = 0; + cluster_id cluster = 1; + AccessRestrictionStruct restrictions[] = 2; + } + + fabric_scoped struct AccessRestrictionEntryStruct { + fabric_sensitive endpoint_no endpoint = 0; + fabric_sensitive cluster_id cluster = 1; + fabric_sensitive AccessRestrictionStruct restrictions[] = 2; + fabric_idx fabricIndex = 254; + } + + struct AccessControlTargetStruct { + nullable cluster_id cluster = 0; + nullable endpoint_no endpoint = 1; + nullable devtype_id deviceType = 2; + } + + fabric_scoped struct AccessControlEntryStruct { + fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; + fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; + nullable fabric_sensitive int64u subjects[] = 3; + nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct AccessControlExtensionStruct { + fabric_sensitive octet_string<128> data = 1; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlEntryStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { + nullable node_id adminNodeID = 1; + nullable int16u adminPasscodeID = 2; + ChangeTypeEnum changeType = 3; + nullable AccessControlExtensionStruct latestValue = 4; + fabric_idx fabricIndex = 254; + } + + fabric_sensitive info event access(read: administer) FabricRestrictionReviewUpdate = 2 { + int64u token = 0; + optional long_char_string instruction = 1; + optional long_char_string ARLRequestFlowUrl = 2; + fabric_idx fabricIndex = 254; + } + + attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; + attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; + readonly attribute int16u subjectsPerAccessControlEntry = 2; + readonly attribute int16u targetsPerAccessControlEntry = 3; + readonly attribute int16u accessControlEntriesPerFabric = 4; + readonly attribute optional CommissioningAccessRestrictionEntryStruct commissioningARL[] = 5; + readonly attribute optional AccessRestrictionEntryStruct arl[] = 6; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ReviewFabricRestrictionsRequest { + CommissioningAccessRestrictionEntryStruct arl[] = 0; + } + + response struct ReviewFabricRestrictionsResponse = 1 { + int64u token = 0; + } + + /** This command signals to the service associated with the device vendor that the fabric administrator would like a review of the current restrictions on the accessing fabric. */ + fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; +} + +/** This cluster provides attributes and events for determining basic information about Nodes, which supports both + Commissioning and operational determination of Node characteristics, such as Vendor ID, Product ID and serial number, + which apply to the whole Node. Also allows setting user device information such as location. */ +cluster BasicInformation = 40 { + revision 3; + + enum ColorEnum : enum8 { + kBlack = 0; + kNavy = 1; + kGreen = 2; + kTeal = 3; + kMaroon = 4; + kPurple = 5; + kOlive = 6; + kGray = 7; + kBlue = 8; + kLime = 9; + kAqua = 10; + kRed = 11; + kFuchsia = 12; + kYellow = 13; + kWhite = 14; + kNickel = 15; + kChrome = 16; + kBrass = 17; + kCopper = 18; + kSilver = 19; + kGold = 20; + } + + enum ProductFinishEnum : enum8 { + kOther = 0; + kMatte = 1; + kSatin = 2; + kPolished = 3; + kRugged = 4; + kFabric = 5; + } + + struct CapabilityMinimaStruct { + int16u caseSessionsPerFabric = 0; + int16u subscriptionsPerFabric = 1; + } + + struct ProductAppearanceStruct { + ProductFinishEnum finish = 0; + nullable ColorEnum primaryColor = 1; + } + + critical event StartUp = 0 { + int32u softwareVersion = 0; + } + + critical event ShutDown = 1 { + } + + info event Leave = 2 { + fabric_idx fabricIndex = 0; + } + + info event ReachableChanged = 3 { + boolean reachableNewValue = 0; + } + + readonly attribute int16u dataModelRevision = 0; + readonly attribute char_string<32> vendorName = 1; + readonly attribute vendor_id vendorID = 2; + readonly attribute char_string<32> productName = 3; + readonly attribute int16u productID = 4; + attribute access(write: manage) char_string<32> nodeLabel = 5; + attribute access(write: administer) char_string<2> location = 6; + readonly attribute int16u hardwareVersion = 7; + readonly attribute char_string<64> hardwareVersionString = 8; + readonly attribute int32u softwareVersion = 9; + readonly attribute char_string<64> softwareVersionString = 10; + readonly attribute optional char_string<16> manufacturingDate = 11; + readonly attribute optional char_string<32> partNumber = 12; + readonly attribute optional long_char_string<256> productURL = 13; + readonly attribute optional char_string<64> productLabel = 14; + readonly attribute optional char_string<32> serialNumber = 15; + attribute access(write: manage) optional boolean localConfigDisabled = 16; + readonly attribute optional boolean reachable = 17; + readonly attribute char_string<32> uniqueID = 18; + readonly attribute CapabilityMinimaStruct capabilityMinima = 19; + readonly attribute optional ProductAppearanceStruct productAppearance = 20; + readonly attribute int32u specificationVersion = 21; + readonly attribute int16u maxPathsPerInvoke = 22; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + command MfgSpecificPing(): DefaultSuccess = 0; +} + +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +cluster LocalizationConfiguration = 43 { + revision 1; // NOTE: Default/not specifically set + + attribute access(write: manage) char_string<35> activeLocale = 0; + readonly attribute char_string supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +cluster PowerSource = 47 { + revision 1; // NOTE: Default/not specifically set + + enum BatApprovedChemistryEnum : enum16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : enum8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : enum8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : enum8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : enum16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : enum8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : enum8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : enum8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : enum8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : enum8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : bitmap32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; + readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; + readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute optional nullable int32u wiredAssessedCurrent = 6; + readonly attribute optional int32u wiredNominalVoltage = 7; + readonly attribute optional int32u wiredMaximumCurrent = 8; + readonly attribute optional boolean wiredPresent = 9; + readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; + readonly attribute optional nullable int32u batVoltage = 11; + readonly attribute optional nullable int8u batPercentRemaining = 12; + readonly attribute optional nullable int32u batTimeRemaining = 13; + readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; + readonly attribute optional boolean batReplacementNeeded = 15; + readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; + readonly attribute optional boolean batPresent = 17; + readonly attribute optional BatFaultEnum activeBatFaults[] = 18; + readonly attribute optional char_string<60> batReplacementDescription = 19; + readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; + readonly attribute optional char_string<20> batANSIDesignation = 21; + readonly attribute optional char_string<20> batIECDesignation = 22; + readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; + readonly attribute optional int32u batCapacity = 24; + readonly attribute optional int8u batQuantity = 25; + readonly attribute optional BatChargeStateEnum batChargeState = 26; + readonly attribute optional nullable int32u batTimeToFullCharge = 27; + readonly attribute optional boolean batFunctionalWhileCharging = 28; + readonly attribute optional nullable int32u batChargingCurrent = 29; + readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; + readonly attribute endpoint_no endpointList[] = 31; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster is used to manage global aspects of the Commissioning flow. */ +cluster GeneralCommissioning = 48 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningErrorEnum : enum8 { + kOK = 0; + kValueOutsideRange = 1; + kInvalidAuthentication = 2; + kNoFailSafe = 3; + kBusyWithOtherAdmin = 4; + kRequiredTCNotAccepted = 5; + kTCAcknowledgementsNotReceived = 6; + kTCMinVersionNotMet = 7; + } + + enum RegulatoryLocationTypeEnum : enum8 { + kIndoor = 0; + kOutdoor = 1; + kIndoorOutdoor = 2; + } + + bitmap Feature : bitmap32 { + kTermsAndConditions = 0x1; + } + + struct BasicCommissioningInfo { + int16u failSafeExpiryLengthSeconds = 0; + int16u maxCumulativeFailsafeSeconds = 1; + } + + attribute access(write: administer) int64u breadcrumb = 0; + readonly attribute BasicCommissioningInfo basicCommissioningInfo = 1; + readonly attribute RegulatoryLocationTypeEnum regulatoryConfig = 2; + readonly attribute RegulatoryLocationTypeEnum locationCapability = 3; + readonly attribute boolean supportsConcurrentConnection = 4; + provisional readonly attribute access(read: administer) optional int16u TCAcceptedVersion = 5; + provisional readonly attribute access(read: administer) optional int16u TCMinRequiredVersion = 6; + provisional readonly attribute access(read: administer) optional bitmap16 TCAcknowledgements = 7; + provisional readonly attribute access(read: administer) optional boolean TCAcknowledgementsRequired = 8; + provisional readonly attribute access(read: administer) optional int32u TCUpdateDeadline = 9; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ArmFailSafeRequest { + int16u expiryLengthSeconds = 0; + int64u breadcrumb = 1; + } + + response struct ArmFailSafeResponse = 1 { + CommissioningErrorEnum errorCode = 0; + char_string<128> debugText = 1; + } + + request struct SetRegulatoryConfigRequest { + RegulatoryLocationTypeEnum newRegulatoryConfig = 0; + char_string<2> countryCode = 1; + int64u breadcrumb = 2; + } + + response struct SetRegulatoryConfigResponse = 3 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + response struct CommissioningCompleteResponse = 5 { + CommissioningErrorEnum errorCode = 0; + char_string debugText = 1; + } + + request struct SetTCAcknowledgementsRequest { + int16u TCVersion = 0; + bitmap16 TCUserResponse = 1; + } + + response struct SetTCAcknowledgementsResponse = 7 { + CommissioningErrorEnum errorCode = 0; + } + + /** Arm the persistent fail-safe timer with an expiry time of now + ExpiryLengthSeconds using device clock */ + command access(invoke: administer) ArmFailSafe(ArmFailSafeRequest): ArmFailSafeResponse = 0; + /** Set the regulatory configuration to be used during commissioning */ + command access(invoke: administer) SetRegulatoryConfig(SetRegulatoryConfigRequest): SetRegulatoryConfigResponse = 2; + /** Signals the Server that the Client has successfully completed all steps of Commissioning/Recofiguration needed during fail-safe period. */ + fabric command access(invoke: administer) CommissioningComplete(): CommissioningCompleteResponse = 4; + /** This command sets the user acknowledgements received in the Enhanced Setup Flow Terms and Conditions into the node. */ + command access(invoke: administer) SetTCAcknowledgements(SetTCAcknowledgementsRequest): SetTCAcknowledgementsResponse = 6; +} + +/** Functionality to configure, enable, disable network credentials and access on a Matter device. */ +cluster NetworkCommissioning = 49 { + revision 1; // NOTE: Default/not specifically set + + enum NetworkCommissioningStatusEnum : enum8 { + kSuccess = 0; + kOutOfRange = 1; + kBoundsExceeded = 2; + kNetworkIDNotFound = 3; + kDuplicateNetworkID = 4; + kNetworkNotFound = 5; + kRegulatoryError = 6; + kAuthFailure = 7; + kUnsupportedSecurity = 8; + kOtherConnectionFailure = 9; + kIPV6Failed = 10; + kIPBindFailed = 11; + kUnknownError = 12; + } + + enum WiFiBandEnum : enum8 { + k2G4 = 0; + k3G65 = 1; + k5G = 2; + k6G = 3; + k60G = 4; + k1G = 5; + } + + bitmap Feature : bitmap32 { + kWiFiNetworkInterface = 0x1; + kThreadNetworkInterface = 0x2; + kEthernetNetworkInterface = 0x4; + kPerDeviceCredentials = 0x8; + } + + bitmap ThreadCapabilitiesBitmap : bitmap16 { + kIsBorderRouterCapable = 0x1; + kIsRouterCapable = 0x2; + kIsSleepyEndDeviceCapable = 0x4; + kIsFullThreadDevice = 0x8; + kIsSynchronizedSleepyEndDeviceCapable = 0x10; + } + + bitmap WiFiSecurityBitmap : bitmap8 { + kUnencrypted = 0x1; + kWEP = 0x2; + kWPAPersonal = 0x4; + kWPA2Personal = 0x8; + kWPA3Personal = 0x10; + kWPA3MatterPDC = 0x20; + } + + struct NetworkInfoStruct { + octet_string<32> networkID = 0; + boolean connected = 1; + optional nullable octet_string<20> networkIdentifier = 2; + optional nullable octet_string<20> clientIdentifier = 3; + } + + struct ThreadInterfaceScanResultStruct { + int16u panId = 0; + int64u extendedPanId = 1; + char_string<16> networkName = 2; + int16u channel = 3; + int8u version = 4; + octet_string<8> extendedAddress = 5; + int8s rssi = 6; + int8u lqi = 7; + } + + struct WiFiInterfaceScanResultStruct { + WiFiSecurityBitmap security = 0; + octet_string<32> ssid = 1; + octet_string<6> bssid = 2; + int16u channel = 3; + WiFiBandEnum wiFiBand = 4; + int8s rssi = 5; + } + + readonly attribute access(read: administer) int8u maxNetworks = 0; + readonly attribute access(read: administer) NetworkInfoStruct networks[] = 1; + readonly attribute optional int8u scanMaxTimeSeconds = 2; + readonly attribute optional int8u connectMaxTimeSeconds = 3; + attribute access(write: administer) boolean interfaceEnabled = 4; + readonly attribute access(read: administer) nullable NetworkCommissioningStatusEnum lastNetworkingStatus = 5; + readonly attribute access(read: administer) nullable octet_string<32> lastNetworkID = 6; + readonly attribute access(read: administer) nullable int32s lastConnectErrorValue = 7; + provisional readonly attribute optional WiFiBandEnum supportedWiFiBands[] = 8; + provisional readonly attribute optional ThreadCapabilitiesBitmap supportedThreadFeatures = 9; + provisional readonly attribute optional int16u threadVersion = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct ScanNetworksRequest { + optional nullable octet_string<32> ssid = 0; + optional int64u breadcrumb = 1; + } + + response struct ScanNetworksResponse = 1 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + optional WiFiInterfaceScanResultStruct wiFiScanResults[] = 2; + optional ThreadInterfaceScanResultStruct threadScanResults[] = 3; + } + + request struct AddOrUpdateWiFiNetworkRequest { + octet_string<32> ssid = 0; + octet_string<64> credentials = 1; + optional int64u breadcrumb = 2; + optional octet_string<140> networkIdentity = 3; + optional octet_string<20> clientIdentifier = 4; + optional octet_string<32> possessionNonce = 5; + } + + request struct AddOrUpdateThreadNetworkRequest { + octet_string<254> operationalDataset = 0; + optional int64u breadcrumb = 1; + } + + request struct RemoveNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct NetworkConfigResponse = 5 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string<512> debugText = 1; + optional int8u networkIndex = 2; + optional octet_string<140> clientIdentity = 3; + optional octet_string<64> possessionSignature = 4; + } + + request struct ConnectNetworkRequest { + octet_string<32> networkID = 0; + optional int64u breadcrumb = 1; + } + + response struct ConnectNetworkResponse = 7 { + NetworkCommissioningStatusEnum networkingStatus = 0; + optional char_string debugText = 1; + nullable int32s errorValue = 2; + } + + request struct ReorderNetworkRequest { + octet_string<32> networkID = 0; + int8u networkIndex = 1; + optional int64u breadcrumb = 2; + } + + request struct QueryIdentityRequest { + octet_string<20> keyIdentifier = 0; + optional octet_string<32> possessionNonce = 1; + } + + response struct QueryIdentityResponse = 10 { + octet_string<140> identity = 0; + optional octet_string<64> possessionSignature = 1; + } + + /** Detemine the set of networks the device sees as available. */ + command access(invoke: administer) ScanNetworks(ScanNetworksRequest): ScanNetworksResponse = 0; + /** Add or update the credentials for a given Wi-Fi network. */ + command access(invoke: administer) AddOrUpdateWiFiNetwork(AddOrUpdateWiFiNetworkRequest): NetworkConfigResponse = 2; + /** Add or update the credentials for a given Thread network. */ + command access(invoke: administer) AddOrUpdateThreadNetwork(AddOrUpdateThreadNetworkRequest): NetworkConfigResponse = 3; + /** Remove the definition of a given network (including its credentials). */ + command access(invoke: administer) RemoveNetwork(RemoveNetworkRequest): NetworkConfigResponse = 4; + /** Connect to the specified network, using previously-defined credentials. */ + command access(invoke: administer) ConnectNetwork(ConnectNetworkRequest): ConnectNetworkResponse = 6; + /** Modify the order in which networks will be presented in the Networks attribute. */ + command access(invoke: administer) ReorderNetwork(ReorderNetworkRequest): NetworkConfigResponse = 8; + /** Retrieve details about and optionally proof of possession of a network client identity. */ + command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; +} + +/** The cluster provides commands for retrieving unstructured diagnostic logs from a Node that may be used to aid in diagnostics. */ +cluster DiagnosticLogs = 50 { + revision 1; // NOTE: Default/not specifically set + + enum IntentEnum : enum8 { + kEndUserSupport = 0; + kNetworkDiag = 1; + kCrashLogs = 2; + } + + enum StatusEnum : enum8 { + kSuccess = 0; + kExhausted = 1; + kNoLogs = 2; + kBusy = 3; + kDenied = 4; + } + + enum TransferProtocolEnum : enum8 { + kResponsePayload = 0; + kBDX = 1; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct RetrieveLogsRequestRequest { + IntentEnum intent = 0; + TransferProtocolEnum requestedProtocol = 1; + optional char_string<32> transferFileDesignator = 2; + } + + response struct RetrieveLogsResponse = 1 { + StatusEnum status = 0; + long_octet_string logContent = 1; + optional epoch_us UTCTimeStamp = 2; + optional systime_us timeSinceBoot = 3; + } + + /** Retrieving diagnostic logs from a Node */ + command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; +} + +/** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster GeneralDiagnostics = 51 { + revision 2; + + enum BootReasonEnum : enum8 { + kUnspecified = 0; + kPowerOnReboot = 1; + kBrownOutReset = 2; + kSoftwareWatchdogReset = 3; + kHardwareWatchdogReset = 4; + kSoftwareUpdateCompleted = 5; + kSoftwareReset = 6; + } + + enum HardwareFaultEnum : enum8 { + kUnspecified = 0; + kRadio = 1; + kSensor = 2; + kResettableOverTemp = 3; + kNonResettableOverTemp = 4; + kPowerSource = 5; + kVisualDisplayFault = 6; + kAudioOutputFault = 7; + kUserInterfaceFault = 8; + kNonVolatileMemoryError = 9; + kTamperDetected = 10; + } + + enum InterfaceTypeEnum : enum8 { + kUnspecified = 0; + kWiFi = 1; + kEthernet = 2; + kCellular = 3; + kThread = 4; + } + + enum NetworkFaultEnum : enum8 { + kUnspecified = 0; + kHardwareFailure = 1; + kNetworkJammed = 2; + kConnectionFailed = 3; + } + + enum RadioFaultEnum : enum8 { + kUnspecified = 0; + kWiFiFault = 1; + kCellularFault = 2; + kThreadFault = 3; + kNFCFault = 4; + kBLEFault = 5; + kEthernetFault = 6; + } + + bitmap Feature : bitmap32 { + kDataModelTest = 0x1; + } + + struct NetworkInterface { + char_string<32> name = 0; + boolean isOperational = 1; + nullable boolean offPremiseServicesReachableIPv4 = 2; + nullable boolean offPremiseServicesReachableIPv6 = 3; + octet_string<8> hardwareAddress = 4; + octet_string IPv4Addresses[] = 5; + octet_string IPv6Addresses[] = 6; + InterfaceTypeEnum type = 7; + } + + critical event HardwareFaultChange = 0 { + HardwareFaultEnum current[] = 0; + HardwareFaultEnum previous[] = 1; + } + + critical event RadioFaultChange = 1 { + RadioFaultEnum current[] = 0; + RadioFaultEnum previous[] = 1; + } + + critical event NetworkFaultChange = 2 { + NetworkFaultEnum current[] = 0; + NetworkFaultEnum previous[] = 1; + } + + critical event BootReason = 3 { + BootReasonEnum bootReason = 0; + } + + readonly attribute NetworkInterface networkInterfaces[] = 0; + readonly attribute int16u rebootCount = 1; + readonly attribute optional int64u upTime = 2; + readonly attribute optional int32u totalOperationalHours = 3; + readonly attribute optional BootReasonEnum bootReason = 4; + readonly attribute optional HardwareFaultEnum activeHardwareFaults[] = 5; + readonly attribute optional RadioFaultEnum activeRadioFaults[] = 6; + readonly attribute optional NetworkFaultEnum activeNetworkFaults[] = 7; + readonly attribute boolean testEventTriggersEnabled = 8; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct TestEventTriggerRequest { + octet_string<16> enableKey = 0; + int64u eventTrigger = 1; + } + + response struct TimeSnapshotResponse = 2 { + systime_ms systemTimeMs = 0; + nullable posix_ms posixTimeMs = 1; + } + + request struct PayloadTestRequestRequest { + octet_string<16> enableKey = 0; + int8u value = 1; + int16u count = 2; + } + + response struct PayloadTestResponse = 4 { + octet_string payload = 0; + } + + /** Provide a means for certification tests to trigger some test-plan-specific events */ + command access(invoke: manage) TestEventTrigger(TestEventTriggerRequest): DefaultSuccess = 0; + /** Take a snapshot of system time and epoch time. */ + command TimeSnapshot(): TimeSnapshotResponse = 1; + /** Request a variable length payload response. */ + command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; +} + +/** The Software Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster SoftwareDiagnostics = 52 { + revision 1; // NOTE: Default/not specifically set + + bitmap Feature : bitmap32 { + kWatermarks = 0x1; + } + + struct ThreadMetricsStruct { + int64u id = 0; + optional char_string<8> name = 1; + optional int32u stackFreeCurrent = 2; + optional int32u stackFreeMinimum = 3; + optional int32u stackSize = 4; + } + + info event SoftwareFault = 0 { + int64u id = 0; + optional char_string name = 1; + optional octet_string faultRecording = 2; + } + + readonly attribute optional ThreadMetricsStruct threadMetrics[] = 0; + readonly attribute optional int64u currentHeapFree = 1; + readonly attribute optional int64u currentHeapUsed = 2; + readonly attribute optional int64u currentHeapHighWatermark = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + /** Reception of this command SHALL reset the values: The StackFreeMinimum field of the ThreadMetrics attribute, CurrentHeapHighWaterMark attribute. */ + command access(invoke: manage) ResetWatermarks(): DefaultSuccess = 0; +} + +/** Commands to trigger a Node to allow a new Administrator to commission it. */ +cluster AdministratorCommissioning = 60 { + revision 1; // NOTE: Default/not specifically set + + enum CommissioningWindowStatusEnum : enum8 { + kWindowNotOpen = 0; + kEnhancedWindowOpen = 1; + kBasicWindowOpen = 2; + } + + enum StatusCode : enum8 { + kBusy = 2; + kPAKEParameterError = 3; + kWindowNotOpen = 4; + } + + bitmap Feature : bitmap32 { + kBasic = 0x1; + } + + readonly attribute CommissioningWindowStatusEnum windowStatus = 0; + readonly attribute nullable fabric_idx adminFabricIndex = 1; + readonly attribute nullable vendor_id adminVendorId = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct OpenCommissioningWindowRequest { + int16u commissioningTimeout = 0; + octet_string PAKEPasscodeVerifier = 1; + int16u discriminator = 2; + int32u iterations = 3; + octet_string<32> salt = 4; + } + + request struct OpenBasicCommissioningWindowRequest { + int16u commissioningTimeout = 0; + } + + /** This command is used by a current Administrator to instruct a Node to go into commissioning mode using enhanced commissioning method. */ + timed command access(invoke: administer) OpenCommissioningWindow(OpenCommissioningWindowRequest): DefaultSuccess = 0; + /** 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. */ + timed command access(invoke: administer) OpenBasicCommissioningWindow(OpenBasicCommissioningWindowRequest): DefaultSuccess = 1; + /** 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. */ + timed command access(invoke: administer) RevokeCommissioning(): DefaultSuccess = 2; +} + +/** This cluster is used to add or remove Operational Credentials on a Commissionee or Node, as well as manage the associated Fabrics. */ +cluster OperationalCredentials = 62 { + revision 1; // NOTE: Default/not specifically set + + enum CertificateChainTypeEnum : enum8 { + kDACCertificate = 1; + kPAICertificate = 2; + } + + enum NodeOperationalCertStatusEnum : enum8 { + kOK = 0; + kInvalidPublicKey = 1; + kInvalidNodeOpId = 2; + kInvalidNOC = 3; + kMissingCsr = 4; + kTableFull = 5; + kInvalidAdminSubject = 6; + kFabricConflict = 9; + kLabelConflict = 10; + kInvalidFabricIndex = 11; + } + + fabric_scoped struct FabricDescriptorStruct { + octet_string<65> rootPublicKey = 1; + vendor_id vendorID = 2; + fabric_id fabricID = 3; + node_id nodeID = 4; + char_string<32> label = 5; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct NOCStruct { + fabric_sensitive octet_string noc = 1; + nullable fabric_sensitive octet_string icac = 2; + fabric_idx fabricIndex = 254; + } + + readonly attribute access(read: administer) NOCStruct NOCs[] = 0; + readonly attribute FabricDescriptorStruct fabrics[] = 1; + readonly attribute int8u supportedFabrics = 2; + readonly attribute int8u commissionedFabrics = 3; + readonly attribute octet_string trustedRootCertificates[] = 4; + readonly attribute int8u currentFabricIndex = 5; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct AttestationRequestRequest { + octet_string<32> attestationNonce = 0; + } + + response struct AttestationResponse = 1 { + octet_string<900> attestationElements = 0; + octet_string<64> attestationSignature = 1; + } + + request struct CertificateChainRequestRequest { + CertificateChainTypeEnum certificateType = 0; + } + + response struct CertificateChainResponse = 3 { + octet_string<600> certificate = 0; + } + + request struct CSRRequestRequest { + octet_string<32> CSRNonce = 0; + optional boolean isForUpdateNOC = 1; + } + + response struct CSRResponse = 5 { + octet_string NOCSRElements = 0; + octet_string attestationSignature = 1; + } + + request struct AddNOCRequest { + octet_string<400> NOCValue = 0; + optional octet_string<400> ICACValue = 1; + octet_string<16> IPKValue = 2; + int64u caseAdminSubject = 3; + vendor_id adminVendorId = 4; + } + + request struct UpdateNOCRequest { + octet_string NOCValue = 0; + optional octet_string ICACValue = 1; + } + + response struct NOCResponse = 8 { + NodeOperationalCertStatusEnum statusCode = 0; + optional fabric_idx fabricIndex = 1; + optional char_string<128> debugText = 2; + } + + request struct UpdateFabricLabelRequest { + char_string<32> label = 0; + } + + request struct RemoveFabricRequest { + fabric_idx fabricIndex = 0; + } + + request struct AddTrustedRootCertificateRequest { + octet_string rootCACertificate = 0; + } + + /** Sender is requesting attestation information from the receiver. */ + command access(invoke: administer) AttestationRequest(AttestationRequestRequest): AttestationResponse = 0; + /** Sender is requesting a device attestation certificate from the receiver. */ + command access(invoke: administer) CertificateChainRequest(CertificateChainRequestRequest): CertificateChainResponse = 2; + /** Sender is requesting a certificate signing request (CSR) from the receiver. */ + command access(invoke: administer) CSRRequest(CSRRequestRequest): CSRResponse = 4; + /** Sender is requesting to add the new node operational certificates. */ + command access(invoke: administer) AddNOC(AddNOCRequest): NOCResponse = 6; + /** Sender is requesting to update the node operational certificates. */ + fabric command access(invoke: administer) UpdateNOC(UpdateNOCRequest): NOCResponse = 7; + /** This command SHALL be used by an Administrative Node to set the user-visible Label field for a given Fabric, as reflected by entries in the Fabrics attribute. */ + fabric command access(invoke: administer) UpdateFabricLabel(UpdateFabricLabelRequest): NOCResponse = 9; + /** This command is used by Administrative Nodes to remove a given fabric index and delete all associated fabric-scoped data. */ + command access(invoke: administer) RemoveFabric(RemoveFabricRequest): NOCResponse = 10; + /** This command SHALL add a Trusted Root CA Certificate, provided as its CHIP Certificate representation. */ + command access(invoke: administer) AddTrustedRootCertificate(AddTrustedRootCertificateRequest): DefaultSuccess = 11; +} + +/** The Group Key Management Cluster is the mechanism by which group keys are managed. */ +cluster GroupKeyManagement = 63 { + revision 1; // NOTE: Default/not specifically set + + enum GroupKeySecurityPolicyEnum : enum8 { + kTrustFirst = 0; + kCacheAndSync = 1; + } + + bitmap Feature : bitmap32 { + kCacheAndSync = 0x1; + } + + fabric_scoped struct GroupInfoMapStruct { + group_id groupId = 1; + endpoint_no endpoints[] = 2; + optional char_string<16> groupName = 3; + fabric_idx fabricIndex = 254; + } + + fabric_scoped struct GroupKeyMapStruct { + group_id groupId = 1; + int16u groupKeySetID = 2; + fabric_idx fabricIndex = 254; + } + + struct GroupKeySetStruct { + int16u groupKeySetID = 0; + GroupKeySecurityPolicyEnum groupKeySecurityPolicy = 1; + nullable octet_string<16> epochKey0 = 2; + nullable epoch_us epochStartTime0 = 3; + nullable octet_string<16> epochKey1 = 4; + nullable epoch_us epochStartTime1 = 5; + nullable octet_string<16> epochKey2 = 6; + nullable epoch_us epochStartTime2 = 7; + } + + attribute access(write: manage) GroupKeyMapStruct groupKeyMap[] = 0; + readonly attribute GroupInfoMapStruct groupTable[] = 1; + readonly attribute int16u maxGroupsPerFabric = 2; + readonly attribute int16u maxGroupKeysPerFabric = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct KeySetWriteRequest { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetReadRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadResponse = 2 { + GroupKeySetStruct groupKeySet = 0; + } + + request struct KeySetRemoveRequest { + int16u groupKeySetID = 0; + } + + response struct KeySetReadAllIndicesResponse = 5 { + int16u groupKeySetIDs[] = 0; + } + + /** Write a new set of keys for the given key set id. */ + fabric command access(invoke: administer) KeySetWrite(KeySetWriteRequest): DefaultSuccess = 0; + /** Read the keys for a given key set id. */ + fabric command access(invoke: administer) KeySetRead(KeySetReadRequest): KeySetReadResponse = 1; + /** Revoke a Root Key from a Group */ + fabric command access(invoke: administer) KeySetRemove(KeySetRemoveRequest): DefaultSuccess = 3; + /** Return the list of Group Key Sets associated with the accessing fabric */ + fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4; +} + +/** The Fixed Label Cluster provides a feature for the device to tag an endpoint with zero or more read only +labels. */ +cluster FixedLabel = 64 { + revision 1; // NOTE: Default/not specifically set + + struct LabelStruct { + char_string<16> label = 0; + char_string<16> value = 1; + } + + readonly attribute LabelStruct labelList[] = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** This cluster provides an interface to a boolean state called StateValue. */ +cluster BooleanState = 69 { + revision 1; + + info event StateChange = 0 { + boolean stateValue = 0; + } + + readonly attribute boolean stateValue = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting air quality classification */ +cluster AirQuality = 91 { + revision 1; // NOTE: Default/not specifically set + + enum AirQualityEnum : enum8 { + kUnknown = 0; + kGood = 1; + kFair = 2; + kModerate = 3; + kPoor = 4; + kVeryPoor = 5; + kExtremelyPoor = 6; + } + + bitmap Feature : bitmap32 { + kFair = 0x1; + kModerate = 0x2; + kVeryPoor = 0x4; + kExtremelyPoor = 0x8; + } + + readonly attribute AirQualityEnum airQuality = 0; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of illuminance, and reporting illuminance measurements. */ +cluster IlluminanceMeasurement = 1024 { + revision 3; + + enum LightSensorTypeEnum : enum8 { + kPhotodiode = 0; + kCMOS = 1; + } + + readonly attribute nullable int16u measuredValue = 0; + readonly attribute nullable int16u minMeasuredValue = 1; + readonly attribute nullable int16u maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute optional nullable LightSensorTypeEnum lightSensorType = 4; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of temperature, and reporting temperature measurements. */ +cluster TemperatureMeasurement = 1026 { + revision 1; // NOTE: Default/not specifically set + + readonly attribute nullable temperature measuredValue = 0; + readonly attribute nullable temperature minMeasuredValue = 1; + readonly attribute nullable temperature maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of pressure, and reporting pressure measurements. */ +cluster PressureMeasurement = 1027 { + revision 3; + + bitmap Feature : bitmap32 { + kExtended = 0x1; + } + + readonly attribute nullable int16s measuredValue = 0; + readonly attribute nullable int16s minMeasuredValue = 1; + readonly attribute nullable int16s maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute optional nullable int16s scaledValue = 16; + readonly attribute optional nullable int16s minScaledValue = 17; + readonly attribute optional nullable int16s maxScaledValue = 18; + readonly attribute optional int16u scaledTolerance = 19; + readonly attribute optional int8s scale = 20; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of flow, and reporting flow measurements. */ +cluster FlowMeasurement = 1028 { + revision 1; // NOTE: Default/not specifically set + + readonly attribute nullable int16u measuredValue = 0; + readonly attribute nullable int16u minMeasuredValue = 1; + readonly attribute nullable int16u maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes and commands for configuring the measurement of relative humidity, and reporting relative humidity measurements. */ +cluster RelativeHumidityMeasurement = 1029 { + revision 3; + + readonly attribute nullable int16u measuredValue = 0; + readonly attribute nullable int16u minMeasuredValue = 1; + readonly attribute nullable int16u maxMeasuredValue = 2; + readonly attribute optional int16u tolerance = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** The server cluster provides an interface to occupancy sensing functionality based on one or more sensing modalities, including configuration and provision of notifications of occupancy status. */ +cluster OccupancySensing = 1030 { + revision 5; + + enum OccupancySensorTypeEnum : enum8 { + kPIR = 0; + kUltrasonic = 1; + kPIRAndUltrasonic = 2; + kPhysicalContact = 3; + } + + bitmap Feature : bitmap32 { + kOther = 0x1; + kPassiveInfrared = 0x2; + kUltrasonic = 0x4; + kPhysicalContact = 0x8; + kActiveInfrared = 0x10; + kRadar = 0x20; + kRFSensing = 0x40; + kVision = 0x80; + } + + bitmap OccupancyBitmap : bitmap8 { + kOccupied = 0x1; + } + + bitmap OccupancySensorTypeBitmap : bitmap8 { + kPIR = 0x1; + kUltrasonic = 0x2; + kPhysicalContact = 0x4; + } + + struct HoldTimeLimitsStruct { + int16u holdTimeMin = 0; + int16u holdTimeMax = 1; + int16u holdTimeDefault = 2; + } + + info event OccupancyChanged = 0 { + OccupancyBitmap occupancy = 0; + } + + readonly attribute OccupancyBitmap occupancy = 0; + readonly attribute OccupancySensorTypeEnum occupancySensorType = 1; + readonly attribute OccupancySensorTypeBitmap occupancySensorTypeBitmap = 2; + attribute access(write: manage) optional int16u holdTime = 3; + readonly attribute optional HoldTimeLimitsStruct holdTimeLimits = 4; + attribute access(write: manage) optional int16u PIROccupiedToUnoccupiedDelay = 16; + attribute access(write: manage) optional int16u PIRUnoccupiedToOccupiedDelay = 17; + attribute access(write: manage) optional int8u PIRUnoccupiedToOccupiedThreshold = 18; + attribute access(write: manage) optional int16u ultrasonicOccupiedToUnoccupiedDelay = 32; + attribute access(write: manage) optional int16u ultrasonicUnoccupiedToOccupiedDelay = 33; + attribute access(write: manage) optional int8u ultrasonicUnoccupiedToOccupiedThreshold = 34; + attribute access(write: manage) optional int16u physicalContactOccupiedToUnoccupiedDelay = 48; + attribute access(write: manage) optional int16u physicalContactUnoccupiedToOccupiedDelay = 49; + attribute access(write: manage) optional int8u physicalContactUnoccupiedToOccupiedThreshold = 50; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting carbon monoxide concentration measurements */ +cluster CarbonMonoxideConcentrationMeasurement = 1036 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting carbon dioxide concentration measurements */ +cluster CarbonDioxideConcentrationMeasurement = 1037 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting nitrogen dioxide concentration measurements */ +cluster NitrogenDioxideConcentrationMeasurement = 1043 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting ozone concentration measurements */ +cluster OzoneConcentrationMeasurement = 1045 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting PM2.5 concentration measurements */ +cluster Pm25ConcentrationMeasurement = 1066 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting formaldehyde concentration measurements */ +cluster FormaldehydeConcentrationMeasurement = 1067 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting PM1 concentration measurements */ +cluster Pm1ConcentrationMeasurement = 1068 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting PM10 concentration measurements */ +cluster Pm10ConcentrationMeasurement = 1069 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting total volatile organic compounds concentration measurements */ +cluster TotalVolatileOrganicCompoundsConcentrationMeasurement = 1070 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +/** Attributes for reporting radon concentration measurements */ +cluster RadonConcentrationMeasurement = 1071 { + revision 3; + + enum LevelValueEnum : enum8 { + kUnknown = 0; + kLow = 1; + kMedium = 2; + kHigh = 3; + kCritical = 4; + } + + enum MeasurementMediumEnum : enum8 { + kAir = 0; + kWater = 1; + kSoil = 2; + } + + enum MeasurementUnitEnum : enum8 { + kPPM = 0; + kPPB = 1; + kPPT = 2; + kMGM3 = 3; + kUGM3 = 4; + kNGM3 = 5; + kPM3 = 6; + kBQM3 = 7; + } + + bitmap Feature : bitmap32 { + kNumericMeasurement = 0x1; + kLevelIndication = 0x2; + kMediumLevel = 0x4; + kCriticalLevel = 0x8; + kPeakMeasurement = 0x10; + kAverageMeasurement = 0x20; + } + + readonly attribute optional nullable single measuredValue = 0; + readonly attribute optional nullable single minMeasuredValue = 1; + readonly attribute optional nullable single maxMeasuredValue = 2; + readonly attribute optional nullable single peakMeasuredValue = 3; + readonly attribute optional elapsed_s peakMeasuredValueWindow = 4; + readonly attribute optional nullable single averageMeasuredValue = 5; + readonly attribute optional elapsed_s averageMeasuredValueWindow = 6; + readonly attribute optional single uncertainty = 7; + readonly attribute optional MeasurementUnitEnum measurementUnit = 8; + readonly attribute optional MeasurementMediumEnum measurementMedium = 9; + readonly attribute optional LevelValueEnum levelValue = 10; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + +endpoint 0 { + device type ma_rootdevice = 22, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AccessControl { + emits event AccessControlEntryChanged; + emits event AccessControlExtensionChanged; + callback attribute acl; + callback attribute extension; + callback attribute subjectsPerAccessControlEntry; + callback attribute targetsPerAccessControlEntry; + callback attribute accessControlEntriesPerFabric; + callback attribute attributeList; + ram attribute featureMap default = 1; + callback attribute clusterRevision; + } + + server cluster BasicInformation { + emits event StartUp; + emits event ShutDown; + emits event Leave; + callback attribute dataModelRevision; + callback attribute vendorName; + callback attribute vendorID; + callback attribute productName; + callback attribute productID; + persist attribute nodeLabel; + callback attribute location; + callback attribute hardwareVersion; + callback attribute hardwareVersionString; + callback attribute softwareVersion; + callback attribute softwareVersionString; + callback attribute manufacturingDate; + callback attribute partNumber; + callback attribute productURL; + callback attribute productLabel; + callback attribute serialNumber; + persist attribute localConfigDisabled default = 0; + callback attribute uniqueID; + callback attribute capabilityMinima; + callback attribute specificationVersion; + callback attribute maxPathsPerInvoke; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } + + server cluster LocalizationConfiguration { + ram attribute activeLocale; + callback attribute supportedLocales; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } + + server cluster GeneralCommissioning { + ram attribute breadcrumb default = 0x0000000000000000; + callback attribute basicCommissioningInfo; + callback attribute regulatoryConfig; + callback attribute locationCapability; + callback attribute supportsConcurrentConnection; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 2; + + handle command ArmFailSafe; + handle command ArmFailSafeResponse; + handle command SetRegulatoryConfig; + handle command SetRegulatoryConfigResponse; + handle command CommissioningComplete; + handle command CommissioningCompleteResponse; + } + + server cluster NetworkCommissioning { + ram attribute maxNetworks; + callback attribute networks; + ram attribute scanMaxTimeSeconds; + ram attribute connectMaxTimeSeconds; + ram attribute interfaceEnabled; + ram attribute lastNetworkingStatus; + ram attribute lastNetworkID; + ram attribute lastConnectErrorValue; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 0x0001; + + handle command ScanNetworks; + handle command ScanNetworksResponse; + handle command AddOrUpdateWiFiNetwork; + handle command AddOrUpdateThreadNetwork; + handle command RemoveNetwork; + handle command NetworkConfigResponse; + handle command ConnectNetwork; + handle command ConnectNetworkResponse; + handle command ReorderNetwork; + } + + server cluster DiagnosticLogs { + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RetrieveLogsRequest; + handle command RetrieveLogsResponse; + } + + server cluster GeneralDiagnostics { + emits event BootReason; + callback attribute networkInterfaces; + callback attribute rebootCount; + callback attribute upTime; + callback attribute totalOperationalHours; + callback attribute bootReason; + callback attribute activeHardwareFaults; + callback attribute activeRadioFaults; + callback attribute activeNetworkFaults; + callback attribute testEventTriggersEnabled default = false; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command TestEventTrigger; + handle command TimeSnapshot; + handle command TimeSnapshotResponse; + } + + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + callback attribute featureMap; + ram attribute clusterRevision default = 0x0001; + + handle command ResetWatermarks; + } + + server cluster AdministratorCommissioning { + callback attribute windowStatus; + callback attribute adminFabricIndex; + callback attribute adminVendorId; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 0x0001; + + handle command OpenCommissioningWindow; + handle command OpenBasicCommissioningWindow; + handle command RevokeCommissioning; + } + + server cluster OperationalCredentials { + callback attribute NOCs; + callback attribute fabrics; + callback attribute supportedFabrics; + callback attribute commissionedFabrics; + callback attribute trustedRootCertificates; + callback attribute currentFabricIndex; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 0x0001; + + handle command AttestationRequest; + handle command AttestationResponse; + handle command CertificateChainRequest; + handle command CertificateChainResponse; + handle command CSRRequest; + handle command CSRResponse; + handle command AddNOC; + handle command UpdateNOC; + handle command NOCResponse; + handle command UpdateFabricLabel; + handle command RemoveFabric; + handle command AddTrustedRootCertificate; + } + + server cluster GroupKeyManagement { + callback attribute groupKeyMap; + callback attribute groupTable; + callback attribute maxGroupsPerFabric; + callback attribute maxGroupKeysPerFabric; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command KeySetWrite; + handle command KeySetRead; + handle command KeySetReadResponse; + handle command KeySetRemove; + handle command KeySetReadAllIndices; + handle command KeySetReadAllIndicesResponse; + } + + server cluster FixedLabel { + callback attribute labelList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 1 { + device type ma_contactsensor = 21, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster BooleanState { + ram attribute stateValue default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + } +} +endpoint 2 { + device type ma_lightsensor = 262, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster IlluminanceMeasurement { + ram attribute measuredValue default = 0xC351; + ram attribute minMeasuredValue default = 1; + ram attribute maxMeasuredValue default = 0xfffe; + ram attribute lightSensorType default = 1; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 3 { + device type ma_occupancysensor = 263, version 4; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster OccupancySensing { + ram attribute occupancy default = 0; + ram attribute occupancySensorType default = 0; + ram attribute occupancySensorTypeBitmap default = 0x1; + callback attribute holdTime; + callback attribute holdTimeLimits; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 5; + } +} +endpoint 4 { + device type ma_tempsensor = 770, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster TemperatureMeasurement { + ram attribute measuredValue default = 2350; + ram attribute minMeasuredValue default = -27315; + ram attribute maxMeasuredValue default = 32767; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 4; + } +} +endpoint 5 { + device type ma_pressuresensor = 773, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster PressureMeasurement { + ram attribute measuredValue default = 0xA; + ram attribute minMeasuredValue default = 1; + ram attribute maxMeasuredValue default = 32767; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 6 { + device type ma_flowsensor = 774, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster FlowMeasurement { + ram attribute measuredValue default = 0xA; + ram attribute minMeasuredValue default = 0x1; + ram attribute maxMeasuredValue default = 0xFFF; + ram attribute tolerance default = 8; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 7 { + device type ma_humiditysensor = 775, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster RelativeHumidityMeasurement { + ram attribute measuredValue default = 0x11d0; + ram attribute minMeasuredValue default = 0x1; + ram attribute maxMeasuredValue default = 0x2710; + ram attribute tolerance default = 8; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } +} +endpoint 8 { + device type ma_air_quality_sensor = 44, version 1; + + binding cluster Binding; + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x00; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + handle command TriggerEffect; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster AirQuality { + callback attribute airQuality; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster CarbonMonoxideConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster CarbonDioxideConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster NitrogenDioxideConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster OzoneConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster Pm25ConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster FormaldehydeConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster Pm1ConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster Pm10ConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster TotalVolatileOrganicCompoundsConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } + + server cluster RadonConcentrationMeasurement { + callback attribute measuredValue; + callback attribute minMeasuredValue; + callback attribute maxMeasuredValue; + callback attribute peakMeasuredValue; + callback attribute peakMeasuredValueWindow; + callback attribute averageMeasuredValue; + callback attribute averageMeasuredValueWindow; + callback attribute uncertainty; + callback attribute measurementUnit; + callback attribute measurementMedium; + callback attribute levelValue; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 3; + } +} +endpoint 9 { + device type ma_powersource = 17, version 1; + + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster PowerSource { + ram attribute status default = 1; + persist attribute order default = 1; + ram attribute description default = "Battery"; + ram attribute batVoltage default = 2590; + ram attribute batPercentRemaining default = 98; + ram attribute batTimeRemaining default = 52560000; + ram attribute batChargeLevel default = 0; + ram attribute batReplacementNeeded default = 0; + ram attribute batReplaceability default = 2; + ram attribute batPresent default = 1; + ram attribute batReplacementDescription default = "2x AA/LR6 Alkaline"; + ram attribute batCommonDesignation default = 2; + ram attribute batApprovedChemistry default = 1; + ram attribute batQuantity; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0x0A; + ram attribute clusterRevision default = 1; + } +} + + diff --git a/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap new file mode 100644 index 0000000000..05d1c22eb2 --- /dev/null +++ b/examples/chef/devices/rootnode_contactsensor_lightsensor_occupancysensor_temperaturesensor_pressuresensor_flowsensor_humiditysensor_airqualitysensor_powersource_367e7cea91.zap @@ -0,0 +1,9272 @@ +{ + "fileFormat": 2, + "featureLevel": 104, + "creator": "zap", + "keyValuePairs": [ + { + "key": "commandDiscovery", + "value": "1" + }, + { + "key": "defaultResponsePolicy", + "value": "always" + }, + { + "key": "manufacturerCodes", + "value": "0x1002" + } + ], + "package": [ + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/zcl/zcl.json", + "type": "zcl-properties", + "category": "matter", + "version": 1, + "description": "Matter SDK ZCL data" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "category": "matter", + "version": "chip-v1" + } + ], + "endpointTypes": [ + { + "id": 1, + "name": "MA-rootdevice", + "deviceTypeRef": { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 22, + "profileId": 259, + "label": "MA-rootdevice", + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 22 + ], + "deviceTypeName": "MA-rootdevice", + "deviceTypeCode": 22, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Access Control", + "code": 31, + "mfgCode": null, + "define": "ACCESS_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ACL", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Extension", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SubjectsPerAccessControlEntry", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetsPerAccessControlEntry", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AccessControlEntriesPerFabric", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "AccessControlEntryChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AccessControlExtensionChanged", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Basic Information", + "code": 40, + "mfgCode": null, + "define": "BASIC_INFORMATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DataModelRevision", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorName", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "VendorID", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductName", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductID", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "NodeLabel", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "Location", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersion", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "HardwareVersionString", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersion", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SoftwareVersionString", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ManufacturingDate", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "PartNumber", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductURL", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "long_char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "ProductLabel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "LocalConfigDisabled", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "NVM", + "singleton": 1, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UniqueID", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CapabilityMinima", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "CapabilityMinimaStruct", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SpecificationVersion", + "code": 21, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxPathsPerInvoke", + "code": 22, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 1, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "StartUp", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ShutDown", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Leave", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Localization Configuration", + "code": 43, + "mfgCode": null, + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "ActiveLocale", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportedLocales", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Commissioning", + "code": 48, + "mfgCode": null, + "define": "GENERAL_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ArmFailSafe", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ArmFailSafeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfig", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissioningCompleteResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SupportsConcurrentConnection", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Network Commissioning", + "code": 49, + "mfgCode": null, + "define": "NETWORK_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ScanNetworks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ScanNetworksResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateWiFiNetwork", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddOrUpdateThreadNetwork", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveNetwork", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NetworkConfigResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ConnectNetwork", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ConnectNetworkResponse", + "code": 7, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ReorderNetwork", + "code": 8, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "MaxNetworks", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Networks", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ScanMaxTimeSeconds", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ConnectMaxTimeSeconds", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "InterfaceEnabled", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkingStatus", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "NetworkCommissioningStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastNetworkID", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "octet_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LastConnectErrorValue", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 1, + "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", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RetrieveLogsResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshot", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshotResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveHardwareFaults", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveRadioFaults", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveNetworkFaults", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "BootReason", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Software Diagnostics", + "code": 52, + "mfgCode": null, + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "ThreadMetrics", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapFree", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapUsed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentHeapHighWatermark", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Administrator Commissioning", + "code": 60, + "mfgCode": null, + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "OpenCommissioningWindow", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OpenBasicCommissioningWindow", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RevokeCommissioning", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "WindowStatus", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "CommissioningWindowStatusEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminFabricIndex", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "fabric_idx", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AdminVendorId", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "vendor_id", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Operational Credentials", + "code": 62, + "mfgCode": null, + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "AttestationRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AttestationResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CertificateChainRequest", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CertificateChainResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CSRRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CSRResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "AddNOC", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NOCResponse", + "code": 8, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "UpdateFabricLabel", + "code": 9, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NOCs", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0001", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Fixed Label", + "code": 64, + "mfgCode": null, + "define": "FIXED_LABEL_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "LabelList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 21, + "profileId": 259, + "label": "MA-contactsensor", + "name": "MA-contactsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 21, + "profileId": 259, + "label": "MA-contactsensor", + "name": "MA-contactsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 21 + ], + "deviceTypeName": "MA-contactsensor", + "deviceTypeCode": 21, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Boolean State", + "code": 69, + "mfgCode": null, + "define": "BOOLEAN_STATE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "StateValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 3, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 262, + "profileId": 259, + "label": "MA-lightsensor", + "name": "MA-lightsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 262, + "profileId": 259, + "label": "MA-lightsensor", + "name": "MA-lightsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 262 + ], + "deviceTypeName": "MA-lightsensor", + "deviceTypeCode": 262, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Illuminance Measurement", + "code": 1024, + "mfgCode": null, + "define": "ILLUMINANCE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xC351", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xfffe", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LightSensorType", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "LightSensorTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 4, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 263, + "profileId": 259, + "label": "MA-occupancysensor", + "name": "MA-occupancysensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 263, + "profileId": 259, + "label": "MA-occupancysensor", + "name": "MA-occupancysensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 4 + ], + "deviceIdentifiers": [ + 263 + ], + "deviceTypeName": "MA-occupancysensor", + "deviceTypeCode": 263, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Occupancy Sensing", + "code": 1030, + "mfgCode": null, + "define": "OCCUPANCY_SENSING_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Occupancy", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "OccupancyBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OccupancySensorType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "OccupancySensorTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "OccupancySensorTypeBitmap", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "OccupancySensorTypeBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HoldTime", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HoldTimeLimits", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "HoldTimeLimitsStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 5, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 770, + "profileId": 259, + "label": "MA-tempsensor", + "name": "MA-tempsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 770 + ], + "deviceTypeName": "MA-tempsensor", + "deviceTypeCode": 770, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Temperature Measurement", + "code": 1026, + "mfgCode": null, + "define": "TEMPERATURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2350", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "-27315", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "temperature", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "32767", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "4", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 6, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 773, + "profileId": 259, + "label": "MA-pressuresensor", + "name": "MA-pressuresensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 773, + "profileId": 259, + "label": "MA-pressuresensor", + "name": "MA-pressuresensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 773 + ], + "deviceTypeName": "MA-pressuresensor", + "deviceTypeCode": 773, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Pressure Measurement", + "code": 1027, + "mfgCode": null, + "define": "PRESSURE_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xA", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "32767", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 7, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 774, + "profileId": 259, + "label": "MA-flowsensor", + "name": "MA-flowsensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 774, + "profileId": 259, + "label": "MA-flowsensor", + "name": "MA-flowsensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 774 + ], + "deviceTypeName": "MA-flowsensor", + "deviceTypeCode": 774, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Flow Measurement", + "code": 1028, + "mfgCode": null, + "define": "FLOW_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xA", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0xFFF", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "8", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 8, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 775, + "profileId": 259, + "label": "MA-humiditysensor", + "name": "MA-humiditysensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 775, + "profileId": 259, + "label": "MA-humiditysensor", + "name": "MA-humiditysensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 775 + ], + "deviceTypeName": "MA-humiditysensor", + "deviceTypeCode": 775, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Relative Humidity Measurement", + "code": 1029, + "mfgCode": null, + "define": "RELATIVE_HUMIDITY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x11d0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x2710", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Tolerance", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "8", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 9, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 44, + "profileId": 259, + "label": "MA-air-quality-sensor", + "name": "MA-air-quality-sensor", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 44, + "profileId": 259, + "label": "MA-air-quality-sensor", + "name": "MA-air-quality-sensor", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 44 + ], + "deviceTypeName": "MA-air-quality-sensor", + "deviceTypeCode": 44, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Binding", + "code": 30, + "mfgCode": null, + "define": "BINDING_CLUSTER", + "side": "client", + "enabled": 1 + }, + { + "name": "Air Quality", + "code": 91, + "mfgCode": null, + "define": "AIR_QUALITY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "AirQuality", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "AirQualityEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Carbon Monoxide Concentration Measurement", + "code": 1036, + "mfgCode": null, + "define": "CARBON_MONOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Carbon Dioxide Concentration Measurement", + "code": 1037, + "mfgCode": null, + "define": "CARBON_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Nitrogen Dioxide Concentration Measurement", + "code": 1043, + "mfgCode": null, + "define": "NITROGEN_DIOXIDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Ozone Concentration Measurement", + "code": 1045, + "mfgCode": null, + "define": "OZONE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "PM2.5 Concentration Measurement", + "code": 1066, + "mfgCode": null, + "define": "PM2_5_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Formaldehyde Concentration Measurement", + "code": 1067, + "mfgCode": null, + "define": "FORMALDEHYDE_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "PM1 Concentration Measurement", + "code": 1068, + "mfgCode": null, + "define": "PM1_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "PM10 Concentration Measurement", + "code": 1069, + "mfgCode": null, + "define": "PM10_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Total Volatile Organic Compounds Concentration Measurement", + "code": 1070, + "mfgCode": null, + "define": "TVOC_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Radon Concentration Measurement", + "code": 1071, + "mfgCode": null, + "define": "RADON_CONCENTRATION_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "MeasuredValue", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MinMeasuredValue", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxMeasuredValue", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValue", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeakMeasuredValueWindow", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValue", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AverageMeasuredValueWindow", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Uncertainty", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "single", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementUnit", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "MeasurementUnitEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MeasurementMedium", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "MeasurementMediumEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelValue", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "LevelValueEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 10, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 17, + "profileId": 259, + "label": "MA-powersource", + "name": "MA-powersource", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 17, + "profileId": 259, + "label": "MA-powersource", + "name": "MA-powersource", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 17 + ], + "deviceTypeName": "MA-powersource", + "deviceTypeCode": 17, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "Battery", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2590", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPercentRemaining", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "98", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatTimeRemaining", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "52560000", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatChargeLevel", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "BatChargeLevelEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementNeeded", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplaceability", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "BatReplaceabilityEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatPresent", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatReplacementDescription", + "code": 19, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2x AA/LR6 Alkaline", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatCommonDesignation", + "code": 20, + "mfgCode": null, + "side": "server", + "type": "BatCommonDesignationEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatApprovedChemistry", + "code": 23, + "mfgCode": null, + "side": "server", + "type": "BatApprovedChemistryEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BatQuantity", + "code": 25, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0A", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + } + ], + "endpoints": [ + { + "endpointTypeName": "MA-rootdevice", + "endpointTypeIndex": 0, + "profileId": 259, + "endpointId": 0, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 1, + "profileId": 259, + "endpointId": 1, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 2, + "profileId": 259, + "endpointId": 2, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 3, + "profileId": 259, + "endpointId": 3, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 4, + "profileId": 259, + "endpointId": 4, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 5, + "profileId": 259, + "endpointId": 5, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 6, + "profileId": 259, + "endpointId": 6, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 7, + "profileId": 259, + "endpointId": 7, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 8, + "profileId": 259, + "endpointId": 8, + "networkId": 0, + "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 9, + "profileId": 259, + "endpointId": 9, + "networkId": 0, + "parentEndpointIdentifier": null + } + ] +} \ No newline at end of file From be06550ff895afe52bd55f72607b2dfae0f59225 Mon Sep 17 00:00:00 2001 From: PeterC1965 <101805108+PeterC1965@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:26:05 +0000 Subject: [PATCH 019/219] FIX TC_EEVSE_2_3 test fail when run in EST timezone (#36500) * Ensure calculation of target_time_delta in compute_expected_target_time_as_epoch_s is done fully in UTC * Restyled by autopep8 --------- Co-authored-by: Restyled.io --- src/python_testing/TC_EEVSE_2_3.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/python_testing/TC_EEVSE_2_3.py b/src/python_testing/TC_EEVSE_2_3.py index eb4e43d0b5..54c5baa1a7 100644 --- a/src/python_testing/TC_EEVSE_2_3.py +++ b/src/python_testing/TC_EEVSE_2_3.py @@ -194,8 +194,10 @@ def compute_expected_target_time_as_epoch_s(self, minutes_past_midnight): f"{int(minutes_past_midnight/60)}:{int(minutes_past_midnight%60)}" f" Expected target_time = {target_time}") - target_time_delta = target_time - \ - datetime(2000, 1, 1, 0, 0, 0, 0).astimezone(timezone.utc) + matter_base_time = datetime(2000, 1, 1, 0, 0, 0, 0, tzinfo=timezone.utc) + + target_time_delta = target_time - matter_base_time + expected_target_time_epoch_s = int(target_time_delta.total_seconds()) return expected_target_time_epoch_s From a6253abcf7b33c3150400ea2d31c3a494d8008b7 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 15 Nov 2024 12:27:31 -0500 Subject: [PATCH 020/219] Improve detection of "historical" events in Matter.framework. (#36506) We were marking events as "historical" if there were any attributes in the same report that have the C quality. This had a few problems: * Some devices randomly report C-quality attributes, for various reasons. * Some attributes stop having the C quality in favor of Q, in some cases, so this is not very forward-compatible. The fix is to remove this C-quality check altogether. At that point we have the following situations: 1. We're setting up a new subscription and getting our initial priming report. This case will still have _receivingPrimingReport set, and will cause any events reported as part of priming to be marked "historical". 2. We are getting a "priming" report from a server-side subscription resumption after the server timed out on a subscription. If this happens before the max-interval elapses, we will see this as a normal report on our subscription, but with all attributes and events the server knows about included. In this case, we mark ourselves as being in a "priming report" if we get an event that has an event number we have already seen, so that we mark any not-seen-before events in that report as "historical", since we don't know how long ago they are from. 3. We are getting a normal incremental report, and will not mark any such events as "historical". Since we are now keeping track of last-received event numbers, we can also use those for our subscriptions and can filter out any events that have an event number no greater than our last-observed one. --- .../Framework/CHIP/MTRDevice_Concrete.mm | 76 +++++++++++++++---- .../Framework/CHIPTests/MTRDeviceTests.m | 74 +++++++++++++++++- 2 files changed, 135 insertions(+), 15 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 9169507634..35cfbcf7d8 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -219,7 +219,23 @@ @interface MTRDevice_Concrete () @property (nonatomic, readonly) os_unfair_lock timeSyncLock; @property (nonatomic) NSMutableArray *> * unreportedEvents; + +// The highest event number we have observed, if there was one at all. +@property (nonatomic, readwrite, nullable) NSNumber * highestObservedEventNumber; + +// receivingReport is true if we are receving a subscription report. In +// particular, this will be false if we're just getting an attribute value from +// a read-through. @property (nonatomic) BOOL receivingReport; + +// receivingPrimingReport is true if this subscription report is part of us +// establishing a new subscription to the device. When this is true, it is +// _not_ guaranteed that any particular set of attributes will be reported +// (e.g. everything could be filtered out by our DataVersion filters). +// Conversely, when this is false that tells us nothing about attributes _not_ +// being reported: a device could randomly decide to rev all data versions and +// report all attributes at any point in time, for example due to performing +// subscription resumption. @property (nonatomic) BOOL receivingPrimingReport; // TODO: instead of all the BOOL properties that are some facet of the state, move to internal state machine that has (at least): @@ -390,6 +406,7 @@ - (instancetype)initWithNodeID:(NSNumber *)nodeID controller:(MTRDeviceControlle } _clusterDataToPersist = nil; _persistedClusters = [NSMutableSet set]; + _highestObservedEventNumber = nil; // If there is a data store, make sure we have an observer to monitor system clock changes, so // NSDate-based write coalescing could be reset and not get into a bad state. @@ -1954,11 +1971,14 @@ - (void)_injectEventReport:(NSArray *)eventRep return; } - // [_deviceController asyncDispatchToMatterQueue:^{ // TODO: This wasn't used previously, not sure why, so keeping it here for thought, but preserving existing behavior + [self _injectPossiblyInvalidEventReport:eventReport]; +} + +- (void)_injectPossiblyInvalidEventReport:(NSArray *)eventReport +{ dispatch_async(self.queue, ^{ [self _handleEventReport:eventReport]; }); - // } errorHandler: nil]; } // END DRAGON: This is used by the XPC Server to inject attribute reports @@ -1966,7 +1986,9 @@ - (void)_injectEventReport:(NSArray *)eventRep #ifdef DEBUG - (void)unitTestInjectEventReport:(NSArray *> *)eventReport { - [self _injectEventReport:eventReport]; + // Don't validate incoming event reports for unit tests, because we want to + // allow incoming event reports without an MTREventIsHistoricalKey. + [self _injectPossiblyInvalidEventReport:eventReport]; } - (void)unitTestInjectAttributeReport:(NSArray *> *)attributeReport fromSubscription:(BOOL)isFromSubscription @@ -2102,11 +2124,33 @@ - (void)_handleEventReport:(NSArray *> *)eventRepor } } - NSMutableDictionary * eventToReturn = eventDict.mutableCopy; - if (_receivingPrimingReport) { - eventToReturn[MTREventIsHistoricalKey] = @(YES); + auto * eventNumber = MTR_SAFE_CAST(eventDict[MTREventNumberKey], NSNumber); + if (!eventNumber) { + MTR_LOG_ERROR("%@ Event %@ missing event number", self, eventDict); + continue; + } + + if (!self.highestObservedEventNumber || + [self.highestObservedEventNumber compare:eventNumber] == NSOrderedAscending) { + // This is an event we have not seen before. + self.highestObservedEventNumber = eventNumber; } else { - eventToReturn[MTREventIsHistoricalKey] = @(NO); + // We have seen this event already; just filter it out. But also, we must be getting + // some sort of priming report if we are getting events we have seen before. + if (_receivingReport) { + _receivingPrimingReport = YES; + } + continue; + } + + NSMutableDictionary * eventToReturn = eventDict.mutableCopy; + // If MTREventIsHistoricalKey is already present, do not mess with the value. + if (eventToReturn[MTREventIsHistoricalKey] == nil) { + if (_receivingPrimingReport) { + eventToReturn[MTREventIsHistoricalKey] = @(YES); + } else { + eventToReturn[MTREventIsHistoricalKey] = @(NO); + } } [reportToReturn addObject:eventToReturn]; @@ -2558,8 +2602,15 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason // Set up a cluster state cache. We just want this for the logic it has for // tracking data versions and event numbers so we minimize the amount of data we // request on resubscribes, so tell it not to store data. + Optional highestObservedEventNumber; + { + std::lock_guard lock(self->_lock); + if (self.highestObservedEventNumber) { + highestObservedEventNumber = MakeOptional(self.highestObservedEventNumber.unsignedLongLongValue); + } + } auto clusterStateCache = std::make_unique(*callback.get(), - /* highestReceivedEventNumber = */ NullOptional, + highestObservedEventNumber, /* cacheData = */ false); auto readClient = std::make_unique(InteractionModelEngine::GetInstance(), exchangeManager, clusterStateCache->GetBufferedCallback(), ReadClient::InteractionType::Subscribe); @@ -2609,6 +2660,10 @@ - (void)_setupSubscriptionWithReason:(NSString *)reason attributePath.release(); eventPath.release(); + // NOTE: We don't set the event number field in readParams, and just let + // the ReadClient get the min event number information from the cluster + // state cache. + // TODO: Change from local filter list generation to rehydrating ClusterStateCache to take advantage of existing filter list sorting algorithm // SendAutoResubscribeRequest cleans up the params, even on failure. @@ -3587,11 +3642,6 @@ - (NSArray *)_getAttributesToReportWithReportedValues:(NSArray *> * eventReport) { eventReportsReceived += eventReport.count; @@ -1489,6 +1490,7 @@ - (void)test017_TestMTRDeviceBasics if (!reportEnded) { NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey]; XCTAssertTrue(reportIsHistorical.boolValue); + lastObservedEventNumber = eventDict[MTREventNumberKey]; } else { if (!gotOneNonPrimingEvent) { NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey]; @@ -1509,7 +1511,7 @@ - (void)test017_TestMTRDeviceBasics MTREventTimestampDateKey : [NSDate date], MTREventIsHistoricalKey : @(NO), MTREventPriorityKey : @(MTREventPriorityInfo), - MTREventNumberKey : @(1), // Doesn't matter, in practice + MTREventNumberKey : @(lastObservedEventNumber.unsignedLongLongValue + 1), MTRDataKey : @ { MTRTypeKey : MTRStructureValueType, MTRValueKey : @[], @@ -3899,6 +3901,70 @@ - (void)test034_TestMTRDeviceHistoricalEvents // Must have gotten some events (at least StartUp!) XCTAssertTrue(eventReportsReceived > 0); + + // Now try doing some event injection. + __block uint64_t eventNumber = 0x1000000; // Should't have that many events on the device yet! + __block uint64_t firstNewEventNumber = eventNumber; + __auto_type createEventReport = ^{ + return @{ + MTREventPathKey : [MTREventPath eventPathWithEndpointID:@(1) clusterID:@(1) eventID:@(1)], + MTREventTimeTypeKey : @(MTREventTimeTypeTimestampDate), + MTREventTimestampDateKey : [NSDate date], + MTREventPriorityKey : @(MTREventPriorityInfo), + MTREventNumberKey : @(eventNumber++), + MTRDataKey : @ { + MTRTypeKey : MTRStructureValueType, + MTRValueKey : @[], + }, + }; + }; + + eventReportsReceived = 0; + const int eventReportsToInject = 5; + __block XCTestExpectation * eventReportsFinishedExpectation = [self expectationWithDescription:@"Injecting some new event reports"]; + __block int historicalEvents = 0; + __block int eventReportsToExpect = eventReportsToInject; + + delegate.onEventDataReceived = ^(NSArray *> * eventReport) { + eventReportsReceived += eventReport.count; + for (NSDictionary * eventDict in eventReport) { + NSNumber * reportIsHistorical = eventDict[MTREventIsHistoricalKey]; + NSNumber * eventNumber = eventDict[MTREventNumberKey]; + XCTAssertEqual(reportIsHistorical.boolValue, eventNumber.unsignedLongLongValue < firstNewEventNumber, + @"eventNumber: %@, firstNewEventNumber: %llu", eventNumber, firstNewEventNumber); + historicalEvents += reportIsHistorical.boolValue; + } + + if (eventReportsReceived >= eventReportsToExpect) { + [eventReportsFinishedExpectation fulfill]; + } + }; + + for (int i = 0; i < eventReportsToInject; ++i) { + [device unitTestInjectEventReport:@[ createEventReport() ]]; + } + + [self waitForExpectations:@[ eventReportsFinishedExpectation ] timeout:kTimeoutInSeconds]; + XCTAssertEqual(historicalEvents, 0); + + // Now inject some mix of historical and non-historical events. Since this + // includes events with old event numbers, those should get filtered out + // from reporting. + const uint64_t expectedHistoricalEvents = 2; + firstNewEventNumber = eventNumber; + eventNumber -= expectedHistoricalEvents; + eventReportsReceived = 0; + historicalEvents = 0; + // Events with already-observed event numbers do not get reported. + eventReportsToExpect = eventReportsToInject - expectedHistoricalEvents; + eventReportsFinishedExpectation = [self expectationWithDescription:@"Injecting a mix of old and new reports"]; + + for (int i = 0; i < eventReportsToInject; ++i) { + [device unitTestInjectEventReport:@[ createEventReport() ]]; + } + + [self waitForExpectations:@[ eventReportsFinishedExpectation ] timeout:kTimeoutInSeconds]; + XCTAssertEqual(historicalEvents, 0); } - (void)test035_TestMTRDeviceSubscriptionNotEstablishedOverXPC @@ -4266,13 +4332,17 @@ - (void)test037_MTRDeviceMultipleDelegatesGetReports - (NSDictionary *)_testEventResponseValueWithEndpointID:(NSNumber *)endpointID clusterID:(NSNumber *)clusterID eventID:(NSNumber *)eventID { + // Pick a large event number, so that in practice these event reports will + // all have larger event numbers than anything that might have been observed + // before. + static uint64_t eventNumber = 0x100000000llu; return @{ MTREventPathKey : [MTREventPath eventPathWithEndpointID:endpointID clusterID:clusterID eventID:eventID], MTREventTimeTypeKey : @(MTREventTimeTypeTimestampDate), MTREventTimestampDateKey : [NSDate date], MTREventIsHistoricalKey : @(NO), MTREventPriorityKey : @(MTREventPriorityInfo), - MTREventNumberKey : @(1), // Doesn't matter, in practice + MTREventNumberKey : @(eventNumber++), // Empty payload. MTRDataKey : @ { MTRTypeKey : MTRStructureValueType, From 3efd3d6654dd75b3867f4f412279c82d5b91f207 Mon Sep 17 00:00:00 2001 From: Vatsal Ghelani <152916324+vatsalghelani-csa@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:36:17 -0500 Subject: [PATCH 021/219] Added the data_model_xmls.gni within matter testing infrastructure for data model python packaging (#36499) * Added data models gni file and consumed it using via BUILD.gn * Update build_python.sh with chip testing wheel modifications * Restyled by gn --------- Co-authored-by: Restyled.io --- scripts/build_python.sh | 2 +- .../matter_testing_infrastructure/BUILD.gn | 37 +- .../data_model_xmls.gni | 564 ++++++++++++++++++ .../pyproject.toml | 17 - .../matter_testing_infrastructure/setup.cfg | 21 - .../matter_testing_infrastructure/setup.py | 17 - 6 files changed, 594 insertions(+), 64 deletions(-) create mode 100644 src/python_testing/matter_testing_infrastructure/data_model_xmls.gni delete mode 100644 src/python_testing/matter_testing_infrastructure/pyproject.toml delete mode 100644 src/python_testing/matter_testing_infrastructure/setup.cfg delete mode 100644 src/python_testing/matter_testing_infrastructure/setup.py diff --git a/scripts/build_python.sh b/scripts/build_python.sh index 7f03815f3f..649aeeeec1 100755 --- a/scripts/build_python.sh +++ b/scripts/build_python.sh @@ -182,7 +182,7 @@ ninja -C "$OUTPUT_ROOT" python_wheels WHEEL=("$OUTPUT_ROOT"/controller/python/chip*.whl) # Add the matter_testing_infrastructure wheel -WHEEL+=("$OUTPUT_ROOT"/python/obj/src/python_testing/matter_testing_infrastructure/chip-testing._build_wheel/chip_testing-*.whl) +WHEEL+=("$OUTPUT_ROOT"/obj/src/python_testing/matter_testing_infrastructure/chip-testing._build_wheel/chip_testing*.whl) if [ "$install_pytest_requirements" = "yes" ]; then # Add the matter_yamltests_distribution wheel diff --git a/src/python_testing/matter_testing_infrastructure/BUILD.gn b/src/python_testing/matter_testing_infrastructure/BUILD.gn index 19c7aee68d..64e27b47bb 100644 --- a/src/python_testing/matter_testing_infrastructure/BUILD.gn +++ b/src/python_testing/matter_testing_infrastructure/BUILD.gn @@ -14,16 +14,21 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") - import("//build_overrides/pigweed.gni") +import("//src/python_testing/matter_testing_infrastructure/data_model_xmls.gni") import("$dir_pw_build/python.gni") +import("$dir_pw_build/python_dist.gni") -pw_python_package("chip-testing") { - setup = [ - "setup.py", - "setup.cfg", - "pyproject.toml", - ] +pw_python_package("chip-testing-module") { + generate_setup = { + metadata = { + name = "chip-testing-module" + version = "1.4.0" + author = "Project CHIP Authors" + license_expression = "Apache-2.0" # Consistent license format + url = "https://github.com/project-chip/connectedhomeip" + } + } inputs = [ "env_test.yaml" ] @@ -41,9 +46,25 @@ pw_python_package("chip-testing") { "chip/testing/taglist_and_topology_test.py", "chip/testing/tasks.py", ] - tests = [ "chip/testing/test_metadata.py", "chip/testing/test_tasks.py", ] } + +pw_python_distribution("chip-testing") { + packages = [ ":chip-testing-module" ] + + generate_setup_cfg = { + name = "chip-testing" + version = "1.4.0" + include_default_pyproject_file = true + include_extra_files_in_package_data = true + } + + # Use the imported data_model_XMLS directly + extra_files = [] + foreach(file, data_model_XMLS) { + extra_files += [ "${file} > chip/testing/${file}" ] + } +} diff --git a/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni b/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni new file mode 100644 index 0000000000..066537816a --- /dev/null +++ b/src/python_testing/matter_testing_infrastructure/data_model_xmls.gni @@ -0,0 +1,564 @@ +# Copyright (c) 2024 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. + +import("//build_overrides/chip.gni") + +data_model_XMLS = [ + "${chip_root}/data_model/1.3/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/AccountLogin.xml", + "${chip_root}/data_model/1.3/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/1.3/clusters/AirQuality.xml", + "${chip_root}/data_model/1.3/clusters/AlarmBase.xml", + "${chip_root}/data_model/1.3/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/1.3/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/1.3/clusters/AudioOutput.xml", + "${chip_root}/data_model/1.3/clusters/BallastConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/1.3/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/BooleanState.xml", + "${chip_root}/data_model/1.3/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/Channel.xml", + "${chip_root}/data_model/1.3/clusters/ColorControl.xml", + "${chip_root}/data_model/1.3/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/1.3/clusters/ContentControl.xml", + "${chip_root}/data_model/1.3/clusters/ContentLauncher.xml", + "${chip_root}/data_model/1.3/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/1.3/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/1.3/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/1.3/clusters/DoorLock.xml", + "${chip_root}/data_model/1.3/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/1.3/clusters/EnergyPreference.xml", + "${chip_root}/data_model/1.3/clusters/FanControl.xml", + "${chip_root}/data_model/1.3/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/1.3/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/Groups.xml", + "${chip_root}/data_model/1.3/clusters/ICDManagement.xml", + "${chip_root}/data_model/1.3/clusters/Identify.xml", + "${chip_root}/data_model/1.3/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/KeypadInput.xml", + "${chip_root}/data_model/1.3/clusters/Label-Cluster-FixedLabelCluster.xml", + "${chip_root}/data_model/1.3/clusters/Label-Cluster-LabelCluster.xml", + "${chip_root}/data_model/1.3/clusters/Label-Cluster-UserLabelCluster.xml", + "${chip_root}/data_model/1.3/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/1.3/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/1.3/clusters/LevelControl.xml", + "${chip_root}/data_model/1.3/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/1.3/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/1.3/clusters/LowPower.xml", + "${chip_root}/data_model/1.3/clusters/MediaInput.xml", + "${chip_root}/data_model/1.3/clusters/MediaPlayback.xml", + "${chip_root}/data_model/1.3/clusters/Messages.xml", + "${chip_root}/data_model/1.3/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/1.3/clusters/ModeBase.xml", + "${chip_root}/data_model/1.3/clusters/ModeSelect.xml", + "${chip_root}/data_model/1.3/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.3/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/1.3/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/1.3/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/1.3/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/1.3/clusters/Mode_Oven.xml", + "${chip_root}/data_model/1.3/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/1.3/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/1.3/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/1.3/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/1.3/clusters/OTAProvider.xml", + "${chip_root}/data_model/1.3/clusters/OTARequestor.xml", + "${chip_root}/data_model/1.3/clusters/OccupancySensing.xml", + "${chip_root}/data_model/1.3/clusters/OnOff.xml", + "${chip_root}/data_model/1.3/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/1.3/clusters/OperationalState.xml", + "${chip_root}/data_model/1.3/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/1.3/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/1.3/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/1.3/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/1.3/clusters/PowerTopology.xml", + "${chip_root}/data_model/1.3/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/ProxyConfiguration-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/ProxyDiscovery-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/1.3/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/1.3/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/1.3/clusters/Scenes.xml", + "${chip_root}/data_model/1.3/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.3/clusters/Switch.xml", + "${chip_root}/data_model/1.3/clusters/TargetNavigator.xml", + "${chip_root}/data_model/1.3/clusters/TemperatureControl.xml", + "${chip_root}/data_model/1.3/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/Thermostat.xml", + "${chip_root}/data_model/1.3/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/1.3/clusters/TimeSync.xml", + "${chip_root}/data_model/1.3/clusters/ValidProxies-Cluster.xml", + "${chip_root}/data_model/1.3/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/1.3/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/1.3/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/1.3/clusters/WindowCovering.xml", + "${chip_root}/data_model/1.3/clusters/bridge-clusters-ActionsCluster.xml", + "${chip_root}/data_model/1.3/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/1.3/clusters/cluster_ids.json", + "${chip_root}/data_model/1.3/device_types/Aggregator.xml", + "${chip_root}/data_model/1.3/device_types/AirPurifier.xml", + "${chip_root}/data_model/1.3/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/1.3/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/1.3/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/1.3/device_types/BridgedNode.xml", + "${chip_root}/data_model/1.3/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/1.3/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/1.3/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/1.3/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/1.3/device_types/ContactSensor.xml", + "${chip_root}/data_model/1.3/device_types/ContentApp.xml", + "${chip_root}/data_model/1.3/device_types/ControlBridge.xml", + "${chip_root}/data_model/1.3/device_types/CookSurface.xml", + "${chip_root}/data_model/1.3/device_types/Cooktop.xml", + "${chip_root}/data_model/1.3/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.3/device_types/DimmableLight.xml", + "${chip_root}/data_model/1.3/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/1.3/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/1.3/device_types/Dishwasher.xml", + "${chip_root}/data_model/1.3/device_types/DoorLock.xml", + "${chip_root}/data_model/1.3/device_types/DoorLockController.xml", + "${chip_root}/data_model/1.3/device_types/EVSE.xml", + "${chip_root}/data_model/1.3/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/1.3/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/1.3/device_types/ExtractorHood.xml", + "${chip_root}/data_model/1.3/device_types/Fan.xml", + "${chip_root}/data_model/1.3/device_types/FlowSensor.xml", + "${chip_root}/data_model/1.3/device_types/GenericSwitch.xml", + "${chip_root}/data_model/1.3/device_types/HumiditySensor.xml", + "${chip_root}/data_model/1.3/device_types/LaundryDryer.xml", + "${chip_root}/data_model/1.3/device_types/LaundryWasher.xml", + "${chip_root}/data_model/1.3/device_types/LightSensor.xml", + "${chip_root}/data_model/1.3/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/1.3/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/1.3/device_types/OccupancySensor.xml", + "${chip_root}/data_model/1.3/device_types/OnOffLight.xml", + "${chip_root}/data_model/1.3/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/1.3/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/1.3/device_types/OnOffSensor.xml", + "${chip_root}/data_model/1.3/device_types/OtaProvider.xml", + "${chip_root}/data_model/1.3/device_types/OtaRequestor.xml", + "${chip_root}/data_model/1.3/device_types/Oven.xml", + "${chip_root}/data_model/1.3/device_types/PowerSource.xml", + "${chip_root}/data_model/1.3/device_types/PressureSensor.xml", + "${chip_root}/data_model/1.3/device_types/Pump.xml", + "${chip_root}/data_model/1.3/device_types/PumpController.xml", + "${chip_root}/data_model/1.3/device_types/RainSensor.xml", + "${chip_root}/data_model/1.3/device_types/Refrigerator.xml", + "${chip_root}/data_model/1.3/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/1.3/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/1.3/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/1.3/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.3/device_types/Speaker.xml", + "${chip_root}/data_model/1.3/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/1.3/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/1.3/device_types/Thermostat.xml", + "${chip_root}/data_model/1.3/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/1.3/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/1.3/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/1.3/device_types/WaterValve.xml", + "${chip_root}/data_model/1.3/device_types/WindowCovering.xml", + "${chip_root}/data_model/1.3/device_types/WindowCoveringController.xml", + "${chip_root}/data_model/1.4/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/AccountLogin.xml", + "${chip_root}/data_model/1.4/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/1.4/clusters/AirQuality.xml", + "${chip_root}/data_model/1.4/clusters/AlarmBase.xml", + "${chip_root}/data_model/1.4/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/1.4/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/1.4/clusters/AudioOutput.xml", + "${chip_root}/data_model/1.4/clusters/BallastConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/1.4/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/BooleanState.xml", + "${chip_root}/data_model/1.4/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/Channel.xml", + "${chip_root}/data_model/1.4/clusters/ColorControl.xml", + "${chip_root}/data_model/1.4/clusters/CommissionerControlCluster.xml", + "${chip_root}/data_model/1.4/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/1.4/clusters/ContentControl.xml", + "${chip_root}/data_model/1.4/clusters/ContentLauncher.xml", + "${chip_root}/data_model/1.4/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/1.4/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/1.4/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/1.4/clusters/DoorLock.xml", + "${chip_root}/data_model/1.4/clusters/EcosystemInformationCluster.xml", + "${chip_root}/data_model/1.4/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/1.4/clusters/EnergyPreference.xml", + "${chip_root}/data_model/1.4/clusters/FanControl.xml", + "${chip_root}/data_model/1.4/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/1.4/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/Groups.xml", + "${chip_root}/data_model/1.4/clusters/ICDManagement.xml", + "${chip_root}/data_model/1.4/clusters/Identify.xml", + "${chip_root}/data_model/1.4/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/JointFabricDatastoreCluster.xml", + "${chip_root}/data_model/1.4/clusters/JointFabricPKICluster.xml", + "${chip_root}/data_model/1.4/clusters/KeypadInput.xml", + "${chip_root}/data_model/1.4/clusters/Label-Cluster-FixedLabelCluster.xml", + "${chip_root}/data_model/1.4/clusters/Label-Cluster-LabelCluster.xml", + "${chip_root}/data_model/1.4/clusters/Label-Cluster-UserLabelCluster.xml", + "${chip_root}/data_model/1.4/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/1.4/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/1.4/clusters/LevelControl.xml", + "${chip_root}/data_model/1.4/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/1.4/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/1.4/clusters/LowPower.xml", + "${chip_root}/data_model/1.4/clusters/MediaInput.xml", + "${chip_root}/data_model/1.4/clusters/MediaPlayback.xml", + "${chip_root}/data_model/1.4/clusters/Messages.xml", + "${chip_root}/data_model/1.4/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/1.4/clusters/ModeBase.xml", + "${chip_root}/data_model/1.4/clusters/ModeSelect.xml", + "${chip_root}/data_model/1.4/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.4/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/1.4/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/1.4/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/1.4/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/1.4/clusters/Mode_Oven.xml", + "${chip_root}/data_model/1.4/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/1.4/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/1.4/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/1.4/clusters/Mode_WaterHeater.xml", + "${chip_root}/data_model/1.4/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/1.4/clusters/OTAProvider.xml", + "${chip_root}/data_model/1.4/clusters/OTARequestor.xml", + "${chip_root}/data_model/1.4/clusters/OccupancySensing.xml", + "${chip_root}/data_model/1.4/clusters/OnOff.xml", + "${chip_root}/data_model/1.4/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/1.4/clusters/OperationalState.xml", + "${chip_root}/data_model/1.4/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/1.4/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/1.4/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/1.4/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/1.4/clusters/PowerTopology.xml", + "${chip_root}/data_model/1.4/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/ProxyConfiguration-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/ProxyDiscovery-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/1.4/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/1.4/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/1.4/clusters/Scenes.xml", + "${chip_root}/data_model/1.4/clusters/ServiceArea.xml", + "${chip_root}/data_model/1.4/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.4/clusters/Switch.xml", + "${chip_root}/data_model/1.4/clusters/TargetNavigator.xml", + "${chip_root}/data_model/1.4/clusters/TemperatureControl.xml", + "${chip_root}/data_model/1.4/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/Thermostat.xml", + "${chip_root}/data_model/1.4/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/1.4/clusters/ThreadBorderRouterManagement.xml", + "${chip_root}/data_model/1.4/clusters/ThreadNetworkDirectory.xml", + "${chip_root}/data_model/1.4/clusters/TimeSync.xml", + "${chip_root}/data_model/1.4/clusters/ValidProxies-Cluster.xml", + "${chip_root}/data_model/1.4/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/1.4/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/1.4/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/1.4/clusters/WaterHeaterManagement.xml", + "${chip_root}/data_model/1.4/clusters/WiFiNetworkManagement.xml", + "${chip_root}/data_model/1.4/clusters/WindowCovering.xml", + "${chip_root}/data_model/1.4/clusters/bridge-clusters-ActionsCluster.xml", + "${chip_root}/data_model/1.4/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/1.4/clusters/cluster_ids.json", + "${chip_root}/data_model/1.4/device_types/Aggregator.xml", + "${chip_root}/data_model/1.4/device_types/AirPurifier.xml", + "${chip_root}/data_model/1.4/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/1.4/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/1.4/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/1.4/device_types/BatteryStorage.xml", + "${chip_root}/data_model/1.4/device_types/BridgedNode.xml", + "${chip_root}/data_model/1.4/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/1.4/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/1.4/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/1.4/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/1.4/device_types/ContactSensor.xml", + "${chip_root}/data_model/1.4/device_types/ContentApp.xml", + "${chip_root}/data_model/1.4/device_types/ControlBridge.xml", + "${chip_root}/data_model/1.4/device_types/CookSurface.xml", + "${chip_root}/data_model/1.4/device_types/Cooktop.xml", + "${chip_root}/data_model/1.4/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/1.4/device_types/DimmableLight.xml", + "${chip_root}/data_model/1.4/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/1.4/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/1.4/device_types/Dishwasher.xml", + "${chip_root}/data_model/1.4/device_types/DoorLock.xml", + "${chip_root}/data_model/1.4/device_types/DoorLockController.xml", + "${chip_root}/data_model/1.4/device_types/EVSE.xml", + "${chip_root}/data_model/1.4/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/1.4/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/1.4/device_types/ExtractorHood.xml", + "${chip_root}/data_model/1.4/device_types/Fan.xml", + "${chip_root}/data_model/1.4/device_types/FlowSensor.xml", + "${chip_root}/data_model/1.4/device_types/GenericSwitch.xml", + "${chip_root}/data_model/1.4/device_types/HeatPump.xml", + "${chip_root}/data_model/1.4/device_types/HumiditySensor.xml", + "${chip_root}/data_model/1.4/device_types/JointFabricAdmin.xml", + "${chip_root}/data_model/1.4/device_types/LaundryDryer.xml", + "${chip_root}/data_model/1.4/device_types/LaundryWasher.xml", + "${chip_root}/data_model/1.4/device_types/LightSensor.xml", + "${chip_root}/data_model/1.4/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/1.4/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/1.4/device_types/MountedDimmableLoadControl.xml", + "${chip_root}/data_model/1.4/device_types/MountedOnOffControl.xml", + "${chip_root}/data_model/1.4/device_types/NetworkInfraIntro.xml", + "${chip_root}/data_model/1.4/device_types/NetworkInfraManager.xml", + "${chip_root}/data_model/1.4/device_types/OccupancySensor.xml", + "${chip_root}/data_model/1.4/device_types/OnOffLight.xml", + "${chip_root}/data_model/1.4/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/1.4/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/1.4/device_types/OnOffSensor.xml", + "${chip_root}/data_model/1.4/device_types/OtaProvider.xml", + "${chip_root}/data_model/1.4/device_types/OtaRequestor.xml", + "${chip_root}/data_model/1.4/device_types/Oven.xml", + "${chip_root}/data_model/1.4/device_types/PowerSource.xml", + "${chip_root}/data_model/1.4/device_types/PressureSensor.xml", + "${chip_root}/data_model/1.4/device_types/Pump.xml", + "${chip_root}/data_model/1.4/device_types/PumpController.xml", + "${chip_root}/data_model/1.4/device_types/RainSensor.xml", + "${chip_root}/data_model/1.4/device_types/Refrigerator.xml", + "${chip_root}/data_model/1.4/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/1.4/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/1.4/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/1.4/device_types/SecondaryNetworkInterface.xml", + "${chip_root}/data_model/1.4/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/1.4/device_types/SolarPower.xml", + "${chip_root}/data_model/1.4/device_types/Speaker.xml", + "${chip_root}/data_model/1.4/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/1.4/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/1.4/device_types/Thermostat.xml", + "${chip_root}/data_model/1.4/device_types/ThreadBorderRouter.xml", + "${chip_root}/data_model/1.4/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/1.4/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/1.4/device_types/WaterHeater.xml", + "${chip_root}/data_model/1.4/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/1.4/device_types/WaterValve.xml", + "${chip_root}/data_model/1.4/device_types/WindowCovering.xml", + "${chip_root}/data_model/1.4/device_types/WindowCoveringController.xml", + "${chip_root}/data_model/master/clusters/ACL-Cluster.xml", + "${chip_root}/data_model/master/clusters/AccountLogin.xml", + "${chip_root}/data_model/master/clusters/AdminCommissioningCluster.xml", + "${chip_root}/data_model/master/clusters/AirQuality.xml", + "${chip_root}/data_model/master/clusters/AlarmBase.xml", + "${chip_root}/data_model/master/clusters/ApplicationBasic.xml", + "${chip_root}/data_model/master/clusters/ApplicationLauncher.xml", + "${chip_root}/data_model/master/clusters/AudioOutput.xml", + "${chip_root}/data_model/master/clusters/BallastConfiguration.xml", + "${chip_root}/data_model/master/clusters/BasicInformationCluster.xml", + "${chip_root}/data_model/master/clusters/Binding-Cluster.xml", + "${chip_root}/data_model/master/clusters/BooleanState.xml", + "${chip_root}/data_model/master/clusters/BooleanStateConfiguration.xml", + "${chip_root}/data_model/master/clusters/Channel.xml", + "${chip_root}/data_model/master/clusters/ColorControl.xml", + "${chip_root}/data_model/master/clusters/CommissionerControlCluster.xml", + "${chip_root}/data_model/master/clusters/ConcentrationMeasurement.xml", + "${chip_root}/data_model/master/clusters/ContentAppObserver.xml", + "${chip_root}/data_model/master/clusters/ContentControl.xml", + "${chip_root}/data_model/master/clusters/ContentLauncher.xml", + "${chip_root}/data_model/master/clusters/DemandResponseLoadControl.xml", + "${chip_root}/data_model/master/clusters/Descriptor-Cluster.xml", + "${chip_root}/data_model/master/clusters/DeviceEnergyManagement.xml", + "${chip_root}/data_model/master/clusters/DiagnosticLogsCluster.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsEthernet.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsGeneral.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsSoftware.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsThread.xml", + "${chip_root}/data_model/master/clusters/DiagnosticsWiFi.xml", + "${chip_root}/data_model/master/clusters/DishwasherAlarm.xml", + "${chip_root}/data_model/master/clusters/DoorLock.xml", + "${chip_root}/data_model/master/clusters/ElectricalEnergyMeasurement.xml", + "${chip_root}/data_model/master/clusters/ElectricalPowerMeasurement.xml", + "${chip_root}/data_model/master/clusters/EnergyCalendar.xml", + "${chip_root}/data_model/master/clusters/EnergyEVSE.xml", + "${chip_root}/data_model/master/clusters/EnergyPreference.xml", + "${chip_root}/data_model/master/clusters/EnergyPrice.xml", + "${chip_root}/data_model/master/clusters/FanControl.xml", + "${chip_root}/data_model/master/clusters/FlowMeasurement.xml", + "${chip_root}/data_model/master/clusters/GeneralCommissioningCluster.xml", + "${chip_root}/data_model/master/clusters/Group-Key-Management-Cluster.xml", + "${chip_root}/data_model/master/clusters/Groups.xml", + "${chip_root}/data_model/master/clusters/Humidistat.xml", + "${chip_root}/data_model/master/clusters/ICDManagement.xml", + "${chip_root}/data_model/master/clusters/Identify.xml", + "${chip_root}/data_model/master/clusters/IlluminanceMeasurement.xml", + "${chip_root}/data_model/master/clusters/JointFabricDatastoreCluster.xml", + "${chip_root}/data_model/master/clusters/JointFabricPKICluster.xml", + "${chip_root}/data_model/master/clusters/KeypadInput.xml", + "${chip_root}/data_model/master/clusters/Label-Cluster-FixedLabelCluster.xml", + "${chip_root}/data_model/master/clusters/Label-Cluster-LabelCluster.xml", + "${chip_root}/data_model/master/clusters/Label-Cluster-UserLabelCluster.xml", + "${chip_root}/data_model/master/clusters/LaundryDryerControls.xml", + "${chip_root}/data_model/master/clusters/LaundryWasherControls.xml", + "${chip_root}/data_model/master/clusters/LevelControl.xml", + "${chip_root}/data_model/master/clusters/LocalizationConfiguration.xml", + "${chip_root}/data_model/master/clusters/LocalizationTimeFormat.xml", + "${chip_root}/data_model/master/clusters/LocalizationUnit.xml", + "${chip_root}/data_model/master/clusters/LowPower.xml", + "${chip_root}/data_model/master/clusters/MediaInput.xml", + "${chip_root}/data_model/master/clusters/MediaPlayback.xml", + "${chip_root}/data_model/master/clusters/Messages.xml", + "${chip_root}/data_model/master/clusters/MeterIdentification.xml", + "${chip_root}/data_model/master/clusters/MicrowaveOvenControl.xml", + "${chip_root}/data_model/master/clusters/ModeBase.xml", + "${chip_root}/data_model/master/clusters/ModeSelect.xml", + "${chip_root}/data_model/master/clusters/Mode_DeviceEnergyManagement.xml", + "${chip_root}/data_model/master/clusters/Mode_Dishwasher.xml", + "${chip_root}/data_model/master/clusters/Mode_EVSE.xml", + "${chip_root}/data_model/master/clusters/Mode_LaundryWasher.xml", + "${chip_root}/data_model/master/clusters/Mode_MicrowaveOven.xml", + "${chip_root}/data_model/master/clusters/Mode_Oven.xml", + "${chip_root}/data_model/master/clusters/Mode_RVCClean.xml", + "${chip_root}/data_model/master/clusters/Mode_RVCRun.xml", + "${chip_root}/data_model/master/clusters/Mode_Refrigerator.xml", + "${chip_root}/data_model/master/clusters/Mode_WaterHeater.xml", + "${chip_root}/data_model/master/clusters/NetworkCommissioningCluster.xml", + "${chip_root}/data_model/master/clusters/NetworkIdentityManagement.xml", + "${chip_root}/data_model/master/clusters/OTAProvider.xml", + "${chip_root}/data_model/master/clusters/OTARequestor.xml", + "${chip_root}/data_model/master/clusters/OccupancySensing.xml", + "${chip_root}/data_model/master/clusters/OnOff.xml", + "${chip_root}/data_model/master/clusters/OperationalCredentialCluster.xml", + "${chip_root}/data_model/master/clusters/OperationalState.xml", + "${chip_root}/data_model/master/clusters/OperationalState_Oven.xml", + "${chip_root}/data_model/master/clusters/OperationalState_RVC.xml", + "${chip_root}/data_model/master/clusters/PowerSourceCluster.xml", + "${chip_root}/data_model/master/clusters/PowerSourceConfigurationCluster.xml", + "${chip_root}/data_model/master/clusters/PowerTopology.xml", + "${chip_root}/data_model/master/clusters/PressureMeasurement.xml", + "${chip_root}/data_model/master/clusters/ProxyConfiguration-Cluster.xml", + "${chip_root}/data_model/master/clusters/ProxyDiscovery-Cluster.xml", + "${chip_root}/data_model/master/clusters/PumpConfigurationControl.xml", + "${chip_root}/data_model/master/clusters/RefrigeratorAlarm.xml", + "${chip_root}/data_model/master/clusters/ResourceMonitoring.xml", + "${chip_root}/data_model/master/clusters/Scenes.xml", + "${chip_root}/data_model/master/clusters/ServiceArea.xml", + "${chip_root}/data_model/master/clusters/SmokeCOAlarm.xml", + "${chip_root}/data_model/master/clusters/Switch.xml", + "${chip_root}/data_model/master/clusters/TargetNavigator.xml", + "${chip_root}/data_model/master/clusters/TemperatureControl.xml", + "${chip_root}/data_model/master/clusters/TemperatureMeasurement.xml", + "${chip_root}/data_model/master/clusters/Thermostat.xml", + "${chip_root}/data_model/master/clusters/ThermostatUserInterfaceConfiguration.xml", + "${chip_root}/data_model/master/clusters/ThreadBorderRouterManagement.xml", + "${chip_root}/data_model/master/clusters/ThreadNetworkDirectory.xml", + "${chip_root}/data_model/master/clusters/TimeSync.xml", + "${chip_root}/data_model/master/clusters/ValidProxies-Cluster.xml", + "${chip_root}/data_model/master/clusters/ValveConfigurationControl.xml", + "${chip_root}/data_model/master/clusters/WakeOnLAN.xml", + "${chip_root}/data_model/master/clusters/WaterContentMeasurement.xml", + "${chip_root}/data_model/master/clusters/WaterHeaterManagement.xml", + "${chip_root}/data_model/master/clusters/WiFiNetworkManagement.xml", + "${chip_root}/data_model/master/clusters/WindowCovering.xml", + "${chip_root}/data_model/master/clusters/bridge-clusters-ActionsCluster.xml", + "${chip_root}/data_model/master/clusters/bridge-clusters-BridgedDeviceBasicInformationCluster.xml", + "${chip_root}/data_model/master/clusters/bridge-clusters-EcosystemInformationCluster.xml", + "${chip_root}/data_model/master/clusters/cluster_ids.json", + "${chip_root}/data_model/master/device_types/Aggregator.xml", + "${chip_root}/data_model/master/device_types/AirPurifier.xml", + "${chip_root}/data_model/master/device_types/AirQualitySensor.xml", + "${chip_root}/data_model/master/device_types/BaseDeviceType.xml", + "${chip_root}/data_model/master/device_types/BasicVideoPlayer.xml", + "${chip_root}/data_model/master/device_types/BatteryStorage.xml", + "${chip_root}/data_model/master/device_types/BridgedNode.xml", + "${chip_root}/data_model/master/device_types/CastingVideoClient.xml", + "${chip_root}/data_model/master/device_types/CastingVideoPlayer.xml", + "${chip_root}/data_model/master/device_types/ColorDimmerSwitch.xml", + "${chip_root}/data_model/master/device_types/ColorTemperatureLight.xml", + "${chip_root}/data_model/master/device_types/ContactSensor.xml", + "${chip_root}/data_model/master/device_types/ContentApp.xml", + "${chip_root}/data_model/master/device_types/ControlBridge.xml", + "${chip_root}/data_model/master/device_types/CookSurface.xml", + "${chip_root}/data_model/master/device_types/Cooktop.xml", + "${chip_root}/data_model/master/device_types/DeviceEnergyManagement.xml", + "${chip_root}/data_model/master/device_types/DimmableLight.xml", + "${chip_root}/data_model/master/device_types/DimmablePlug-InUnit.xml", + "${chip_root}/data_model/master/device_types/DimmerSwitch.xml", + "${chip_root}/data_model/master/device_types/Dishwasher.xml", + "${chip_root}/data_model/master/device_types/DoorLock.xml", + "${chip_root}/data_model/master/device_types/DoorLockController.xml", + "${chip_root}/data_model/master/device_types/EVSE.xml", + "${chip_root}/data_model/master/device_types/ElectricalSensor.xml", + "${chip_root}/data_model/master/device_types/EnergyTariff.xml", + "${chip_root}/data_model/master/device_types/EnergyTariffCalendar.xml", + "${chip_root}/data_model/master/device_types/ExtendedColorLight.xml", + "${chip_root}/data_model/master/device_types/ExtractorHood.xml", + "${chip_root}/data_model/master/device_types/Fan.xml", + "${chip_root}/data_model/master/device_types/FlowSensor.xml", + "${chip_root}/data_model/master/device_types/GenericSwitch.xml", + "${chip_root}/data_model/master/device_types/HeatPump.xml", + "${chip_root}/data_model/master/device_types/HumidifierDehumidifier.xml", + "${chip_root}/data_model/master/device_types/HumiditySensor.xml", + "${chip_root}/data_model/master/device_types/JointFabricAdmin.xml", + "${chip_root}/data_model/master/device_types/LaundryDryer.xml", + "${chip_root}/data_model/master/device_types/LaundryWasher.xml", + "${chip_root}/data_model/master/device_types/LightSensor.xml", + "${chip_root}/data_model/master/device_types/MicrowaveOven.xml", + "${chip_root}/data_model/master/device_types/ModeSelectDeviceType.xml", + "${chip_root}/data_model/master/device_types/MountedDimmableLoadControl.xml", + "${chip_root}/data_model/master/device_types/MountedOnOffControl.xml", + "${chip_root}/data_model/master/device_types/NetworkInfraIntro.xml", + "${chip_root}/data_model/master/device_types/NetworkInfraManager.xml", + "${chip_root}/data_model/master/device_types/OccupancySensor.xml", + "${chip_root}/data_model/master/device_types/OnOffLight.xml", + "${chip_root}/data_model/master/device_types/OnOffLightSwitch.xml", + "${chip_root}/data_model/master/device_types/OnOffPlug-inUnit.xml", + "${chip_root}/data_model/master/device_types/OnOffSensor.xml", + "${chip_root}/data_model/master/device_types/OtaProvider.xml", + "${chip_root}/data_model/master/device_types/OtaRequestor.xml", + "${chip_root}/data_model/master/device_types/Oven.xml", + "${chip_root}/data_model/master/device_types/PowerSource.xml", + "${chip_root}/data_model/master/device_types/PressureSensor.xml", + "${chip_root}/data_model/master/device_types/Pump.xml", + "${chip_root}/data_model/master/device_types/PumpController.xml", + "${chip_root}/data_model/master/device_types/RainSensor.xml", + "${chip_root}/data_model/master/device_types/Refrigerator.xml", + "${chip_root}/data_model/master/device_types/RoboticVacuumCleaner.xml", + "${chip_root}/data_model/master/device_types/RoomAirConditioner.xml", + "${chip_root}/data_model/master/device_types/RootNodeDeviceType.xml", + "${chip_root}/data_model/master/device_types/SecondaryNetworkInterface.xml", + "${chip_root}/data_model/master/device_types/SmokeCOAlarm.xml", + "${chip_root}/data_model/master/device_types/SolarPower.xml", + "${chip_root}/data_model/master/device_types/Speaker.xml", + "${chip_root}/data_model/master/device_types/TemperatureControlledCabinet.xml", + "${chip_root}/data_model/master/device_types/TemperatureSensor.xml", + "${chip_root}/data_model/master/device_types/Thermostat.xml", + "${chip_root}/data_model/master/device_types/ThreadBorderRouter.xml", + "${chip_root}/data_model/master/device_types/VideoRemoteControl.xml", + "${chip_root}/data_model/master/device_types/WaterFreezeDetector.xml", + "${chip_root}/data_model/master/device_types/WaterHeater.xml", + "${chip_root}/data_model/master/device_types/WaterLeakDetector.xml", + "${chip_root}/data_model/master/device_types/WaterValve.xml", + "${chip_root}/data_model/master/device_types/WindowCovering.xml", + "${chip_root}/data_model/master/device_types/WindowCoveringController.xml", +] diff --git a/src/python_testing/matter_testing_infrastructure/pyproject.toml b/src/python_testing/matter_testing_infrastructure/pyproject.toml deleted file mode 100644 index f62115ec75..0000000000 --- a/src/python_testing/matter_testing_infrastructure/pyproject.toml +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024 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. - -[build-system] -requires = ['setuptools', 'wheel'] -build-backend = 'setuptools.build_meta' diff --git a/src/python_testing/matter_testing_infrastructure/setup.cfg b/src/python_testing/matter_testing_infrastructure/setup.cfg deleted file mode 100644 index 862236aa03..0000000000 --- a/src/python_testing/matter_testing_infrastructure/setup.cfg +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2024 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. - -[metadata] -name = chip-testing -version = 1.0.0 -author = Project CHIP Authors -license-expression = Apache-2.0 -description = Various helpers associated with the python_testing scripts -url = https://github.com/project-chip/connectedhomeip diff --git a/src/python_testing/matter_testing_infrastructure/setup.py b/src/python_testing/matter_testing_infrastructure/setup.py deleted file mode 100644 index ab0a7f39ad..0000000000 --- a/src/python_testing/matter_testing_infrastructure/setup.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2024 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. - -import setuptools # type: ignore - -setuptools.setup() # Package definition in setup.cfg From d73c821f1f592717e41e1e2efd9751ee6877ed9e Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Sat, 16 Nov 2024 02:37:08 +0900 Subject: [PATCH 022/219] Fix crash in NamedPipeCommands.cpp caused by stack-buffer-underflow (#36465) * Fix stack-buffer-underflow in NamedPipeCommands.cpp * Update NamedPipeCommands.cpp --- examples/platform/linux/NamedPipeCommands.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/platform/linux/NamedPipeCommands.cpp b/examples/platform/linux/NamedPipeCommands.cpp index c77165e900..e07ea242f0 100644 --- a/examples/platform/linux/NamedPipeCommands.cpp +++ b/examples/platform/linux/NamedPipeCommands.cpp @@ -81,12 +81,15 @@ void * NamedPipeCommands::EventCommandListenerTask(void * arg) break; } - ssize_t readBytes = read(fd, readbuf, kChipEventCmdBufSize); - readbuf[readBytes - 1] = '\0'; - ChipLogProgress(NotSpecified, "Received payload: \"%s\"", readbuf); + ssize_t readBytes = read(fd, readbuf, kChipEventCmdBufSize); + if (readBytes > 0) + { + readbuf[readBytes - 1] = '\0'; + ChipLogProgress(NotSpecified, "Received payload: \"%s\"", readbuf); - // Process the received command request from event fifo - self->mDelegate->OnEventCommandReceived(readbuf); + // Process the received command request from event fifo + self->mDelegate->OnEventCommandReceived(readbuf); + } close(fd); } From b155ce16d2b7226c8801b63fa305f96f87017cac Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Sat, 16 Nov 2024 01:37:35 +0800 Subject: [PATCH 023/219] ESP32: Fix compile error for esp32h2 and add config for dynamic server (#36432) * ESP32: Fix compile error for esp32h2 and add config for dynamic server * add esp_wifi_lib if wifi enabled --- config/esp32/components/chip/CMakeLists.txt | 10 ++++++++-- config/esp32/components/chip/Kconfig | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index f3e919d3b6..40f5c0cea2 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -310,6 +310,10 @@ if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE) target_include_directories(${COMPONENT_LIB} INTERFACE "${CHIP_ROOT}/src/tracing/esp32_trace/include") endif() +if (CONFIG_CHIP_DEVICE_ENABLE_DYNAMIC_SERVER) + chip_gn_arg_append("chip_build_controller_dynamic_server" "true") +endif() + set(args_gn_input "${CMAKE_CURRENT_BINARY_DIR}/args.gn.in") file(GENERATE OUTPUT "${args_gn_input}" CONTENT "${chip_gn_args}") @@ -508,9 +512,11 @@ endif() idf_component_get_property(lwip_lib lwip COMPONENT_LIB) list(APPEND chip_libraries $) +if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3" OR CONFIG_ESP32_WIFI_ENABLED) + idf_component_get_property(esp_wifi_lib esp_wifi COMPONENT_LIB) + list(APPEND chip_libraries $) +endif() -idf_component_get_property(esp_wifi_lib esp_wifi COMPONENT_LIB) -list(APPEND chip_libraries $) if (CONFIG_ESP32_WIFI_ENABLED) idf_component_get_property(esp_wifi_dir esp_wifi COMPONENT_DIR) if (CONFIG_IDF_TARGET_ESP32C2) diff --git a/config/esp32/components/chip/Kconfig b/config/esp32/components/chip/Kconfig index 83d3f1c893..2d8127900e 100644 --- a/config/esp32/components/chip/Kconfig +++ b/config/esp32/components/chip/Kconfig @@ -193,6 +193,13 @@ menu "CHIP Core" help Specifies the maximum number of group key sets supported per fabric. + config CHIP_DEVICE_ENABLE_DYNAMIC_SERVER + bool "Enable dynamic server" + default n + help + Enable dynamic server to handle a different interaction model dispatch. + Can be implied when users do not want to use the same server clusters. + endmenu # "General Options" menu "Networking Options" From 4c53f7d488d5e29fb732dedda1705a777f5f1508 Mon Sep 17 00:00:00 2001 From: Marius Tache <102153746+marius-alex-tache@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:38:33 +0200 Subject: [PATCH 024/219] [script] Add core.symlinks=true to submodules init (#36498) On Windows, symlinks in submodules are detected as simple text files. Adding this option to the git submodule command correctly detects the symlinks. Signed-off-by: marius-alex-tache --- scripts/checkout_submodules.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/checkout_submodules.py b/scripts/checkout_submodules.py index 4d527148c7..78b51435eb 100755 --- a/scripts/checkout_submodules.py +++ b/scripts/checkout_submodules.py @@ -113,7 +113,8 @@ def checkout_modules(modules: list, shallow: bool, force: bool, recursive: bool, names = ', '.join([module.name for module in modules]) logging.info(f'Checking out: {names}') - cmd = ['git', '-C', CHIP_ROOT, 'submodule', '--quiet', 'update', '--init'] + cmd = ['git', '-c', 'core.symlinks=true', '-C', CHIP_ROOT] + cmd += ['submodule', '--quiet', 'update', '--init'] cmd += ['--depth', '1'] if shallow else [] cmd += ['--force'] if force else [] cmd += ['--recursive'] if recursive else [] From e6bbe667d61f278b83fbe985227592fcce0aa77b Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Fri, 15 Nov 2024 09:39:33 -0800 Subject: [PATCH 025/219] [Darwin] add API to get public key without leaks (with fixes) (#36340) * Initial checkin * Fixing review feedback * Adding braces * Restyled by clang-format * Fixing build * Restyled by clang-format * Fixing annotations * Update src/darwin/Framework/CHIP/MTRKeypair.h Co-authored-by: Boris Zbarsky * separate statements involving _mPublicKey to make compiler happy * use `CFAutorelease` on CoreFoundation typed public key copies * fix indent * implement `copyPublicKey` for `MTRTestKeys`; add TODO note about optional method calls * remove comment it's a test; this is the best we can do with an optional protocol method * consistent formatting for `copyPublicKey` calls * reformat `copyPublicKey` in `MTRTestKeys` remove comment - not this method's job to worry about other implementation's potential side-effects * Update src/darwin/Framework/CHIP/MTRKeypair.h Co-authored-by: Boris Zbarsky * re-add `publicKey` in `CHIPToolKeypair` check compatibility in CI before going back and removing * use `copyPublicKey` in more places * dedupe public key cache population for CHIPToolKeypair * Restyled by clang-format * try manually releasing pubkey in test * leakfix: MTRP256KeypairBridge * leakfix: `MTRCertificateTests.testGenerateCSR` * remove unnecessary plain `publicKey` implementation * temporarily do the inelegant patch on CFAutorelease * fix another remaining `publicKey` instance * Restyled by clang-format * fix `publicKey` deprecation, marking for future release --------- Co-authored-by: Justin Wood Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../commands/common/CHIPCommandBridge.mm | 9 ++- .../commands/common/CHIPToolKeypair.h | 2 +- .../commands/common/CHIPToolKeypair.mm | 10 ++- src/darwin/Framework/CHIP/MTRCertificates.mm | 19 ++++- .../CHIP/MTRDeviceControllerFactory.mm | 19 ++++- src/darwin/Framework/CHIP/MTRKeypair.h | 14 ++-- .../Framework/CHIP/MTRP256KeypairBridge.mm | 12 +++- .../Framework/CHIPTests/MTRCertificateTests.m | 71 ++++++++++++++----- .../CHIPTests/MTRCertificateValidityTests.m | 5 +- .../CHIPTests/MTRControllerAdvertisingTests.m | 5 +- .../Framework/CHIPTests/MTRControllerTests.m | 59 +++++++++++---- .../Framework/CHIPTests/MTRFabricInfoTests.m | 5 +- .../CHIPTests/MTRPerControllerStorageTests.m | 7 +- .../CHIPTests/TestHelpers/MTRTestKeys.m | 6 ++ 14 files changed, 199 insertions(+), 44 deletions(-) diff --git a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm index 69071d4c42..6b9dfcec29 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPCommandBridge.mm @@ -172,10 +172,17 @@ NSError * error; __auto_type * operationalKeypair = [certificateIssuer issueOperationalKeypairWithControllerStorage:controllerStorage error:&error]; + SecKeyRef publicKey = [operationalKeypair copyPublicKey]; + __auto_type * operational = [certificateIssuer issueOperationalCertificateForNodeID:nodeId fabricID:fabricId - publicKey:operationalKeypair.publicKey + publicKey:publicKey error:&error]; + + if (publicKey != NULL) { + CFAutorelease(publicKey); + } + VerifyOrReturnError(nil == error, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Can not issue an operational certificate: %@", error)); __auto_type * controllerStorageQueue = dispatch_queue_create("com.chip.storage", DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); diff --git a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h index f0ee3f8db6..58be7f2ac4 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h +++ b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.h @@ -22,7 +22,7 @@ @interface CHIPToolKeypair : NSObject - (BOOL)initialize; - (NSData *)signMessageECDSA_RAW:(NSData *)message; -- (SecKeyRef)publicKey; +- (SecKeyRef)copyPublicKey; - (CHIP_ERROR)Serialize:(chip::Crypto::P256SerializedKeypair &)output; - (CHIP_ERROR)Deserialize:(chip::Crypto::P256SerializedKeypair &)input; - (CHIP_ERROR)createOrLoadKeys:(id)storage; diff --git a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm index ce0ef5819b..a09975d68d 100644 --- a/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm +++ b/examples/darwin-framework-tool/commands/common/CHIPToolKeypair.mm @@ -65,7 +65,7 @@ - (NSData *)signMessageECDSA_RAW:(NSData *)message return out_signature; } -- (SecKeyRef)publicKey +- (SecKeyRef)copyPublicKey { if (_mPublicKey == nil) { chip::Crypto::P256PublicKey publicKey = _mKeyPair.Pubkey(); @@ -79,7 +79,13 @@ - (SecKeyRef)publicKey }; _mPublicKey = SecKeyCreateWithData((__bridge CFDataRef) publicKeyNSData, (__bridge CFDictionaryRef) attributes, nullptr); } - return _mPublicKey; + + if (_mPublicKey) { + CFRetain(_mPublicKey); + return _mPublicKey; + } + + return NULL; } - (CHIP_ERROR)Deserialize:(chip::Crypto::P256SerializedKeypair &)input diff --git a/src/darwin/Framework/CHIP/MTRCertificates.mm b/src/darwin/Framework/CHIP/MTRCertificates.mm index b153cf4442..7dcec96cba 100644 --- a/src/darwin/Framework/CHIP/MTRCertificates.mm +++ b/src/darwin/Framework/CHIP/MTRCertificates.mm @@ -152,7 +152,24 @@ + (MTRCertificateDERBytes _Nullable)createOperationalCertificate:(id + (BOOL)keypair:(id)keypair matchesCertificate:(NSData *)certificate { P256PublicKey keypairPubKey; - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(keypair.publicKey, &keypairPubKey); + SecKeyRef publicKey = NULL; + + if ([keypair respondsToSelector:@selector(copyPublicKey)]) { + publicKey = [keypair copyPublicKey]; + } else { + publicKey = [keypair publicKey]; + if (publicKey) { + CFRetain(publicKey); + } + } + + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &keypairPubKey); + + if (publicKey != NULL) { + CFRelease(publicKey); + publicKey = NULL; + } + if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from keypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index 9de51431bf..e287ef0446 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -819,7 +819,24 @@ - (BOOL)findMatchingFabric:(FabricTable &)fabricTable } else { // No root certificate means the nocSigner is using the root keys, because // consumers must provide a root certificate whenever an ICA is used. - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(params.nocSigner.publicKey, &pubKey); + SecKeyRef publicKey = NULL; + + if ([params.nocSigner respondsToSelector:@selector(copyPublicKey)]) { + publicKey = [params.nocSigner copyPublicKey]; + } else { + publicKey = [params.nocSigner publicKey]; + if (publicKey) { + CFRetain(publicKey); + } + } + + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &pubKey); + + if (publicKey != NULL) { + CFRelease(publicKey); + publicKey = NULL; + } + if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from MTRKeypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRKeypair.h b/src/darwin/Framework/CHIP/MTRKeypair.h index a4e4521b28..bf664e13aa 100644 --- a/src/darwin/Framework/CHIP/MTRKeypair.h +++ b/src/darwin/Framework/CHIP/MTRKeypair.h @@ -16,6 +16,7 @@ */ #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -31,13 +32,18 @@ NS_ASSUME_NONNULL_BEGIN * framework APIs. */ @protocol MTRKeypair -@required + +@optional /** - * @brief Return public key for the keypair. + * @brief Returns a copy of the public key for the keypair. */ -- (SecKeyRef)publicKey; +- (SecKeyRef)copyPublicKey MTR_NEWLY_AVAILABLE; + +/** + * @brief Returns public key for the keypair without adding a reference. DEPRECATED - please use copyPublicKey, otherwise this will leak. + */ +- (SecKeyRef)publicKey MTR_NEWLY_DEPRECATED("Please implement copyPublicKey, this will leak otherwise"); -@optional /** * @brief A function to sign a message using ECDSA * diff --git a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm index d253baa8db..03a396e27d 100644 --- a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm +++ b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm @@ -132,7 +132,17 @@ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } -CHIP_ERROR MTRP256KeypairBridge::setPubkey() { return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); } +CHIP_ERROR MTRP256KeypairBridge::setPubkey() +{ + if ([mKeypair respondsToSelector:@selector(copyPublicKey)]) { + SecKeyRef publicKey = [mKeypair copyPublicKey]; + auto copyResult = MatterPubKeyFromSecKeyRef(publicKey, &mPubkey); + CFRelease(publicKey); + return copyResult; + } else { + return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); + } +} CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, P256PublicKey * matterPubKey) { diff --git a/src/darwin/Framework/CHIPTests/MTRCertificateTests.m b/src/darwin/Framework/CHIPTests/MTRCertificateTests.m index fb6cfb9ecb..d822028b5c 100644 --- a/src/darwin/Framework/CHIPTests/MTRCertificateTests.m +++ b/src/darwin/Framework/CHIPTests/MTRCertificateTests.m @@ -127,9 +127,13 @@ - (void)testGenerateIntermediateCert __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); + __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -155,13 +159,16 @@ - (void)testGenerateIntermediateCertWithValidityPeriod __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * startDate = [MTRCertificateTests startDateWithTimeIntervalSinceNow:300]; __auto_type * validityPeriod = [[NSDateInterval alloc] initWithStartDate:startDate duration:400]; __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil validityPeriod:validityPeriod @@ -192,13 +199,16 @@ - (void)testGenerateIntermediateCertWithInfiniteValidity __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * startDate = [MTRCertificateTests startDateWithTimeIntervalSinceNow:300]; __auto_type * validityPeriod = [[NSDateInterval alloc] initWithStartDate:startDate endDate:[NSDate distantFuture]]; __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil validityPeriod:validityPeriod @@ -229,6 +239,9 @@ - (void)testGenerateOperationalCertNoIntermediate __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * cats = [[NSMutableSet alloc] initWithCapacity:3]; // High bits are identifier, low bits are version. @@ -238,7 +251,7 @@ - (void)testGenerateOperationalCertNoIntermediate __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:cats @@ -265,6 +278,9 @@ - (void)testGenerateOperationalCertNoIntermediateWithValidityPeriod __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * cats = [[NSMutableSet alloc] initWithCapacity:3]; // High bits are identifier, low bits are version. @@ -277,7 +293,7 @@ - (void)testGenerateOperationalCertNoIntermediateWithValidityPeriod __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:cats @@ -309,6 +325,9 @@ - (void)testGenerateOperationalCertNoIntermediateWithInfiniteValidity __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * cats = [[NSMutableSet alloc] initWithCapacity:3]; // High bits are identifier, low bits are version. @@ -321,7 +340,7 @@ - (void)testGenerateOperationalCertNoIntermediateWithInfiniteValidity __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:cats @@ -353,10 +372,13 @@ - (void)testGenerateOperationalCertWithIntermediate __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediateCert = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:rootCert - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -364,10 +386,13 @@ - (void)testGenerateOperationalCertWithIntermediate __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:intermediateKeys signingCertificate:intermediateCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:nil @@ -394,6 +419,9 @@ - (void)testGenerateOperationalCertErrorCases __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * longCats = [[NSMutableSet alloc] initWithCapacity:4]; [longCats addObject:@0x00010001]; @@ -415,7 +443,7 @@ - (void)testGenerateOperationalCertErrorCases // Check basic case works __auto_type * operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:nil @@ -425,7 +453,7 @@ - (void)testGenerateOperationalCertErrorCases // CATs too long operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:longCats @@ -435,7 +463,7 @@ - (void)testGenerateOperationalCertErrorCases // Multiple CATs with the same identifier but different versions operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:catsWithSameIdentifier @@ -445,7 +473,7 @@ - (void)testGenerateOperationalCertErrorCases // CAT with invalid version operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:catsWithInvalidVersion @@ -455,7 +483,7 @@ - (void)testGenerateOperationalCertErrorCases // Signing key mismatch operationalCert = [MTRCertificates createOperationalCertificate:operationalKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@1 caseAuthenticatedTags:nil @@ -465,7 +493,7 @@ - (void)testGenerateOperationalCertErrorCases // Invalid fabric id operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@0 nodeID:@1 caseAuthenticatedTags:nil @@ -475,7 +503,7 @@ - (void)testGenerateOperationalCertErrorCases // Undefined node id operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@0 caseAuthenticatedTags:nil @@ -485,7 +513,7 @@ - (void)testGenerateOperationalCertErrorCases // Non-operational node id operationalCert = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:rootCert - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@1 nodeID:@(0xFFFFFFFFFFFFFFFFLLU) caseAuthenticatedTags:nil @@ -504,7 +532,16 @@ - (void)testGenerateCSR __auto_type * publicKey = [MTRCertificates publicKeyFromCSR:csr error:nil]; XCTAssertNotNil(publicKey); - SecKeyRef originalKeyRef = [testKeys publicKey]; + SecKeyRef originalKeyRef; + if ([testKeys respondsToSelector:@selector(copyPublicKey)]) { + originalKeyRef = [testKeys copyPublicKey]; + if (originalKeyRef != NULL) { + CFAutorelease(originalKeyRef); + } + } else { + originalKeyRef = [testKeys publicKey]; + } + XCTAssertTrue(originalKeyRef != NULL); NSData * originalPublicKey = (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation(originalKeyRef, nil); diff --git a/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m b/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m index ecc593e843..719be07106 100644 --- a/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m +++ b/src/darwin/Framework/CHIPTests/MTRCertificateValidityTests.m @@ -259,10 +259,13 @@ - (void)initStack:(MTRTestCertificateIssuer *)certificateIssuer __auto_type * controllerOperationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(controllerOperationalKeys); + __auto_type * controllerPublicKey = controllerOperationalKeys.copyPublicKey; + XCTAssert(controllerPublicKey != NULL); + CFAutorelease(controllerPublicKey); __auto_type * controllerOperationalCert = [certificateIssuer issueOperationalCertificateForNode:@(kControllerId) - operationalPublicKey:controllerOperationalKeys.publicKey]; + operationalPublicKey:controllerPublicKey]; XCTAssertNotNil(controllerOperationalCert); __auto_type * params = [[MTRDeviceControllerStartupParams alloc] initWithIPK:certificateIssuer.rootKey.ipk diff --git a/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m b/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m index 4092a38b56..bee6ee90df 100644 --- a/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m +++ b/src/darwin/Framework/CHIPTests/MTRControllerAdvertisingTests.m @@ -164,10 +164,13 @@ - (nullable MTRDeviceController *)startControllerWithRootKeys:(MTRTestKeys *)roo __auto_type * root = [MTRCertificates createRootCertificate:rootKeys issuerID:@(1) fabricID:nil error:error]; XCTAssertNil(*error); XCTAssertNotNil(root); + __auto_type * publicKey = operationalKeys.copyPublicKey; + XCTAssert(publicKey != NULL); + CFAutorelease(publicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:publicKey fabricID:fabricID nodeID:nodeID caseAuthenticatedTags:nil diff --git a/src/darwin/Framework/CHIPTests/MTRControllerTests.m b/src/darwin/Framework/CHIPTests/MTRControllerTests.m index 436a0df230..afd755f8e5 100644 --- a/src/darwin/Framework/CHIPTests/MTRControllerTests.m +++ b/src/darwin/Framework/CHIPTests/MTRControllerTests.m @@ -620,10 +620,13 @@ - (void)testControllerSignerKeyWithIntermediate __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -860,10 +863,12 @@ - (void)testControllerRotateToICA __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -922,10 +927,13 @@ - (void)testControllerRotateFromICA __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -986,10 +994,13 @@ - (void)testControllerRotateICA __auto_type * intermediateKeys1 = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys1); + __auto_type * intermediate1PublicKey = [intermediateKeys1 copyPublicKey]; + XCTAssert(intermediate1PublicKey != NULL); + CFAutorelease(intermediate1PublicKey); __auto_type * intermediate1 = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys1.publicKey + intermediatePublicKey:intermediate1PublicKey issuerID:nil fabricID:nil error:nil]; @@ -997,10 +1008,13 @@ - (void)testControllerRotateICA __auto_type * intermediateKeys2 = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys2); + __auto_type * intermediate2PublicKey = [intermediateKeys2 copyPublicKey]; + XCTAssert(intermediate2PublicKey != NULL); + CFAutorelease(intermediate2PublicKey); __auto_type * intermediate2 = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys2.publicKey + intermediatePublicKey:intermediate2PublicKey issuerID:nil fabricID:nil error:nil]; @@ -1061,10 +1075,13 @@ - (void)testControllerICAWithoutRoot __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -1104,10 +1121,13 @@ - (void)testControllerProvideFullCertChain __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; @@ -1115,10 +1135,13 @@ - (void)testControllerProvideFullCertChain __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:intermediateKeys signingCertificate:intermediate - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil @@ -1179,10 +1202,13 @@ - (void)testControllerProvideCertChainNoICA __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil @@ -1229,10 +1255,13 @@ - (void)testControllerCertChainFabricMismatchRoot __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil @@ -1273,10 +1302,13 @@ - (void)testControllerCertChainFabricMismatchIntermediate __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = [intermediateKeys copyPublicKey]; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:@111 error:nil]; @@ -1284,10 +1316,13 @@ - (void)testControllerCertChainFabricMismatchIntermediate __auto_type * operationalKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(operationalKeys); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + CFAutorelease(operationalPublicKey); __auto_type * operational = [MTRCertificates createOperationalCertificate:intermediateKeys signingCertificate:intermediate - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:@123 nodeID:@456 caseAuthenticatedTags:nil diff --git a/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m b/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m index a980670986..acdc0ea45f 100644 --- a/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m +++ b/src/darwin/Framework/CHIPTests/MTRFabricInfoTests.m @@ -157,10 +157,13 @@ - (void)testFabricInfoTwoFabrics __auto_type * intermediateKeys = [[MTRTestKeys alloc] init]; XCTAssertNotNil(intermediateKeys); + __auto_type * intermediatePublicKey = intermediateKeys.copyPublicKey; + XCTAssert(intermediatePublicKey != NULL); + CFAutorelease(intermediatePublicKey); __auto_type * intermediate = [MTRCertificates createIntermediateCertificate:rootKeys rootCertificate:root - intermediatePublicKey:intermediateKeys.publicKey + intermediatePublicKey:intermediatePublicKey issuerID:nil fabricID:nil error:nil]; diff --git a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m index 1ead4692a2..3d91a64712 100644 --- a/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m +++ b/src/darwin/Framework/CHIPTests/MTRPerControllerStorageTests.m @@ -403,13 +403,18 @@ - (nullable MTRDeviceController *)startControllerWithRootKeys:(MTRTestKeys *)roo XCTAssertNil(*error); XCTAssertNotNil(root); + __auto_type * operationalPublicKey = [operationalKeys copyPublicKey]; + XCTAssert(operationalPublicKey != NULL); + __auto_type * operational = [MTRCertificates createOperationalCertificate:rootKeys signingCertificate:root - operationalPublicKey:operationalKeys.publicKey + operationalPublicKey:operationalPublicKey fabricID:fabricID nodeID:nodeID caseAuthenticatedTags:caseAuthenticatedTags error:error]; + CFRelease(operationalPublicKey); + XCTAssertNil(*error); XCTAssertNotNil(operational); diff --git a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m index e6a74f25bd..090593a41b 100644 --- a/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m +++ b/src/darwin/Framework/CHIPTests/TestHelpers/MTRTestKeys.m @@ -31,6 +31,12 @@ - (NSData *)publicKeyData return (__bridge_transfer NSData *) SecKeyCopyExternalRepresentation([self publicKey], nil); } +- (SecKeyRef)copyPublicKey +{ + CFRetain(_publicKey); + return _publicKey; +} + - (instancetype)init { if (!(self = [super init])) { From 412271bcd8665810677aab39fe181385e065b7eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damian=20Kr=C3=B3lik?= <66667989+Damian-Nordic@users.noreply.github.com> Date: Fri, 15 Nov 2024 20:10:50 +0100 Subject: [PATCH 026/219] [nrfconnect] Fix all-clusters-app settings size (#36501) After switching to building with sysbuild, the source of the settings partition size has changed from the DTS to the partition manager. Make sure the settings partition is 32kB even when building all-clusters-apps without DFU support. Signed-off-by: Damian Krolik --- examples/all-clusters-app/nrfconnect/prj.conf | 3 +++ examples/all-clusters-minimal-app/nrfconnect/prj.conf | 3 +++ 2 files changed, 6 insertions(+) diff --git a/examples/all-clusters-app/nrfconnect/prj.conf b/examples/all-clusters-app/nrfconnect/prj.conf index 5917c3a9c7..075fdd8e9d 100644 --- a/examples/all-clusters-app/nrfconnect/prj.conf +++ b/examples/all-clusters-app/nrfconnect/prj.conf @@ -54,3 +54,6 @@ CONFIG_CHIP_QSPI_NOR=n # Enable the Read Client for binding purposes CONFIG_CHIP_ENABLE_READ_CLIENT=y + +# Increase the settings partition +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 diff --git a/examples/all-clusters-minimal-app/nrfconnect/prj.conf b/examples/all-clusters-minimal-app/nrfconnect/prj.conf index 58dae15804..9e738ba64d 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/prj.conf +++ b/examples/all-clusters-minimal-app/nrfconnect/prj.conf @@ -55,3 +55,6 @@ CONFIG_CHIP_QSPI_NOR=n # Enable Factory Data feature CONFIG_CHIP_FACTORY_DATA=y CONFIG_CHIP_FACTORY_DATA_BUILD=y + +# Increase the settings partition +CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000 From cda1c4d94edfb40871e623dcd5747a1306a618ee Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Fri, 15 Nov 2024 12:20:14 -0800 Subject: [PATCH 027/219] Darwin XPC: allow `NSDate` typed objects in `internalProperties` dictionary (#36514) --- src/darwin/Framework/CHIP/MTRDevice_XPC.mm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm index b500633602..d5356320b2 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_XPC.mm @@ -258,7 +258,8 @@ - (oneway void)deviceConfigurationChanged:(NSNumber *)nodeID - (BOOL)_internalState:(NSDictionary *)dictionary hasValidValuesForKeys:(const NSArray *)keys valueRequired:(BOOL)required { - // All the keys are NSNumber-valued. + // At one point, all keys were NSNumber valued; now there are also NSDates. + // TODO: Create a mapping between keys and their expected types and use that in the type check below. for (NSString * key in keys) { id value = dictionary[key]; if (!value) { @@ -269,7 +270,7 @@ - (BOOL)_internalState:(NSDictionary *)dictionary hasValidValuesForKeys:(const N continue; } - if (!MTR_SAFE_CAST(value, NSNumber)) { + if (!MTR_SAFE_CAST(value, NSNumber) && !MTR_SAFE_CAST(value, NSDate)) { MTR_LOG_ERROR("%@ device:internalStateUpdated: handed state with invalid value for \"%@\": %@", self, key, value); return NO; } From f47f2fe99082b8b75d2dc73595f1479e0cf24d7f Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 15 Nov 2024 15:36:49 -0800 Subject: [PATCH 028/219] [Fabric-Sync] Fix failing to pair sync device (#36510) * Fix failing to pair sync device * Address review comments * Address review commment --- examples/fabric-sync/admin/DeviceManager.cpp | 5 +- examples/fabric-sync/admin/PairingManager.cpp | 5 ++ examples/fabric-sync/bridge/src/Bridge.cpp | 79 +++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 69aa0a583f..f9685295e4 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -450,13 +450,14 @@ void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) for (const auto & endpoint : addedEndpoints) { // print to console - fprintf(stderr, "A new device is added on Endpoint: %u\n", endpoint); + fprintf(stderr, "A new endpoint %u is added on the remote bridge\n", endpoint); } // Process removed endpoints for (const auto & endpoint : removedEndpoints) { - ChipLogProgress(NotSpecified, "Endpoint removed: %u", endpoint); + // print to console + fprintf(stderr, "Endpoint %u removed from the remote bridge\n", endpoint); SyncedDevice * device = FindDeviceByEndpoint(endpoint); diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index ba360051a2..954680fe17 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -467,6 +467,11 @@ void PairingManager::OnCurrentFabricRemove(void * context, NodeId nodeId, CHIP_E self->mPairingDelegate->OnDeviceRemoved(nodeId, err); self->SetPairingDelegate(nullptr); } + + FabricIndex fabricIndex = self->CurrentCommissioner().GetFabricIndex(); + app::InteractionModelEngine::GetInstance()->ShutdownSubscriptions(fabricIndex, nodeId); + ScopedNodeId scopedNodeId(nodeId, fabricIndex); + DeviceManager::Instance().RemoveSyncedDevice(scopedNodeId); } else { diff --git a/examples/fabric-sync/bridge/src/Bridge.cpp b/examples/fabric-sync/bridge/src/Bridge.cpp index 3d0a4af56f..770509957b 100644 --- a/examples/fabric-sync/bridge/src/Bridge.cpp +++ b/examples/fabric-sync/bridge/src/Bridge.cpp @@ -45,6 +45,83 @@ namespace bridge { namespace { +class AdministratorCommissioningCommandHandler : public CommandHandlerInterface +{ +public: + // Register for the AdministratorCommissioning cluster on all endpoints. + AdministratorCommissioningCommandHandler() : + CommandHandlerInterface(Optional::Missing(), AdministratorCommissioning::Id) + {} + + void InvokeCommand(HandlerContext & handlerContext) override; +}; + +void AdministratorCommissioningCommandHandler::InvokeCommand(HandlerContext & handlerContext) +{ + using Protocols::InteractionModel::Status; + + EndpointId endpointId = handlerContext.mRequestPath.mEndpointId; + + if (handlerContext.mRequestPath.mCommandId != AdministratorCommissioning::Commands::OpenCommissioningWindow::Id || + endpointId == kRootEndpointId) + { + // Proceed with default handling in Administrator Commissioning Server + return; + } + + ChipLogProgress(NotSpecified, "Received command to open commissioning window on Endpoint: %d", endpointId); + + handlerContext.SetCommandHandled(); + + AdministratorCommissioning::Commands::OpenCommissioningWindow::DecodableType commandData; + if (DataModel::Decode(handlerContext.mPayload, commandData) != CHIP_NO_ERROR) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::InvalidCommand); + return; + } + + Status status = Status::Failure; + BridgedDevice * device = BridgedDeviceManager::Instance().GetDevice(endpointId); + FabricAdminDelegate * adminDelegate = FabricBridge::Instance().GetDelegate(); + + if (!device) + { + ChipLogError(NotSpecified, "Commissioning window failed to open: device is null"); + return; + } + + if (!adminDelegate) + { + ChipLogError(NotSpecified, "Commissioning window failed to open: adminDelegate is null"); + return; + } + + auto nodeId = device->GetScopedNodeId().GetNodeId(); + auto fabricIndex = device->GetScopedNodeId().GetFabricIndex(); + + Controller::CommissioningWindowVerifierParams params; + params.SetNodeId(nodeId) + .SetTimeout(commandData.commissioningTimeout) + .SetDiscriminator(commandData.discriminator) + .SetIteration(commandData.iterations) + .SetSalt(commandData.salt) + .SetVerifier(commandData.PAKEPasscodeVerifier); + + CHIP_ERROR err = adminDelegate->OpenCommissioningWindow(params, fabricIndex); + + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Commissioning window is now open"); + status = Status::Success; + } + else + { + ChipLogError(NotSpecified, "Failed to open commissioning window. Error: %" CHIP_ERROR_FORMAT, err.Format()); + } + + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status); +} + class BridgedDeviceInformationCommandHandler : public CommandHandlerInterface { public: @@ -115,6 +192,7 @@ void BridgedDeviceInformationCommandHandler::InvokeCommand(HandlerContext & hand BridgedAdministratorCommissioning gBridgedAdministratorCommissioning; BridgedDeviceBasicInformationImpl gBridgedDeviceBasicInformationAttributes; +AdministratorCommissioningCommandHandler gAdministratorCommissioningCommandHandler; BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler; } // namespace @@ -122,6 +200,7 @@ BridgedDeviceInformationCommandHandler gBridgedDeviceInformationCommandHandler; CHIP_ERROR BridgeInit(FabricAdminDelegate * delegate) { MatterEcosystemInformationPluginServerInitCallback(); + CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gAdministratorCommissioningCommandHandler); CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gBridgedDeviceInformationCommandHandler); AttributeAccessInterfaceRegistry::Instance().Register(&gBridgedDeviceBasicInformationAttributes); From b258171cfca7ac466dfacd48ac833a8c1698a099 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 15 Nov 2024 15:37:04 -0800 Subject: [PATCH 029/219] [Fabric-Admin] Set remote bridge after reverse pair the bridge device (#36451) * [Fabric-Admin] Set remote bridge after reverse pair the bridge devide * Add remote bridge to local bridge after pairing * Set the reverse commissioning flag * Do not add device as a bridged device after reverse pairing * Fix compare error * Address review comments --- .../fabric-sync/FabricSyncCommand.cpp | 3 +- .../device_manager/DeviceManager.cpp | 48 +++++++++++-------- .../device_manager/DeviceManager.h | 21 ++++---- .../device_manager/DeviceSynchronization.cpp | 8 +++- .../device_manager/PairingManager.cpp | 12 ++--- examples/fabric-admin/rpc/RpcServer.cpp | 38 +++++++++++++-- 6 files changed, 90 insertions(+), 40 deletions(-) diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index 315bf2f371..e8296fa478 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -57,6 +57,7 @@ void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_E DeviceManager::Instance().UpdateLastUsedNodeId(mBridgeNodeId); DeviceManager::Instance().SubscribeRemoteFabricBridge(); + DeviceManager::Instance().InitCommissionerControl(); if (DeviceManager::Instance().IsLocalBridgeReady()) { @@ -284,7 +285,7 @@ void FabricSyncDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERRO if (err == CHIP_NO_ERROR) { - DeviceManager::Instance().AddSyncedDevice(Device(mAssignedNodeId, mRemoteEndpointId)); + DeviceManager::Instance().AddSyncedDevice(SyncedDevice(mAssignedNodeId, mRemoteEndpointId)); } else { diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 9f40f92a87..7e40a81965 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -72,39 +72,35 @@ void DeviceManager::UpdateLastUsedNodeId(NodeId nodeId) void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; - - if (mRemoteBridgeNodeId != kUndefinedNodeId) - { - mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); - } + ChipLogProgress(NotSpecified, "Set remote bridge NodeId:" ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); } -void DeviceManager::AddSyncedDevice(const Device & device) +void DeviceManager::AddSyncedDevice(const SyncedDevice & device) { mSyncedDevices.insert(device); ChipLogProgress(NotSpecified, "Added synced device: NodeId:" ChipLogFormatX64 ", EndpointId %u", ChipLogValueX64(device.GetNodeId()), device.GetEndpointId()); } -Device * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) +SyncedDevice * DeviceManager::FindDeviceByEndpoint(EndpointId endpointId) { for (auto & device : mSyncedDevices) { if (device.GetEndpointId() == endpointId) { - return const_cast(&device); + return const_cast(&device); } } return nullptr; } -Device * DeviceManager::FindDeviceByNode(NodeId nodeId) +SyncedDevice * DeviceManager::FindDeviceByNode(NodeId nodeId) { for (auto & device : mSyncedDevices) { if (device.GetNodeId() == nodeId) { - return const_cast(&device); + return const_cast(&device); } } return nullptr; @@ -116,8 +112,8 @@ void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) RemoveSynchronizedDevice(scopedNodeId); #endif - NodeId nodeId = scopedNodeId.GetNodeId(); - Device * device = FindDeviceByNode(nodeId); + NodeId nodeId = scopedNodeId.GetNodeId(); + SyncedDevice * device = FindDeviceByNode(nodeId); if (device == nullptr) { ChipLogProgress(NotSpecified, "No device found with NodeId:" ChipLogFormatX64, ChipLogValueX64(nodeId)); @@ -129,6 +125,18 @@ void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); } +void DeviceManager::InitCommissionerControl() +{ + if (mRemoteBridgeNodeId != kUndefinedNodeId) + { + mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); + } + else + { + ChipLogError(NotSpecified, "Failed to initialize the Commissioner Control delegate"); + } +} + void DeviceManager::OpenDeviceCommissioningWindow(ScopedNodeId scopedNodeId, uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) { @@ -212,10 +220,10 @@ void DeviceManager::UnpairLocalFabricBridge() void DeviceManager::SubscribeRemoteFabricBridge() { - ChipLogProgress(NotSpecified, "Start subscription to the remote bridge.") + ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); - CHIP_ERROR error = mBridgeSubscriber.StartSubscription(PairingManager::Instance().CurrentCommissioner(), - mRemoteBridgeNodeId, kAggregatorEndpointId); + CHIP_ERROR error = mBridgeSubscriber.StartSubscription(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, + kAggregatorEndpointId); if (error != CHIP_NO_ERROR) { @@ -354,7 +362,7 @@ void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) std::vector removedEndpoints; // Note: We're using vectors and manual searches instead of set operations - // because we need to work with the Device objects in mSyncedDevices, + // because we need to work with the SyncedDevice objects in mSyncedDevices, // not just their EndpointIds. This approach allows us to access the full // Device information when processing changes. @@ -381,15 +389,16 @@ void DeviceManager::HandleAttributePartsListUpdate(TLV::TLVReader & data) for (const auto & endpoint : addedEndpoints) { // print to console - fprintf(stderr, "A new device is added on Endpoint: %u\n", endpoint); + fprintf(stderr, "A new endpoint %u is added on the remote bridge\n", endpoint); } // Process removed endpoints for (const auto & endpoint : removedEndpoints) { - ChipLogProgress(NotSpecified, "Endpoint removed: %u", endpoint); + // print to console + fprintf(stderr, "Endpoint %u removed from the remote bridge\n", endpoint); - Device * device = FindDeviceByEndpoint(endpoint); + SyncedDevice * device = FindDeviceByEndpoint(endpoint); if (device == nullptr) { @@ -467,6 +476,7 @@ void DeviceManager::HandleCommandResponse(const app::ConcreteCommandPath & path, if (path.mClusterId == app::Clusters::CommissionerControl::Id && path.mCommandId == app::Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Id) { + VerifyOrDie(path.mEndpointId == kAggregatorEndpointId); HandleReverseOpenCommissioningWindow(data); } } diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 594fcfc574..8c273ee53d 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -32,15 +32,15 @@ constexpr uint32_t kDefaultSetupPinCode = 20202021; constexpr uint16_t kDefaultLocalBridgePort = 5540; constexpr uint16_t kResponseTimeoutSeconds = 30; -class Device +class SyncedDevice { public: - Device(chip::NodeId nodeId, chip::EndpointId endpointId) : mNodeId(nodeId), mEndpointId(endpointId) {} + SyncedDevice(chip::NodeId nodeId, chip::EndpointId endpointId) : mNodeId(nodeId), mEndpointId(endpointId) {} chip::NodeId GetNodeId() const { return mNodeId; } chip::EndpointId GetEndpointId() const { return mEndpointId; } - bool operator<(const Device & other) const + bool operator<(const SyncedDevice & other) const { return mNodeId < other.mNodeId || (mNodeId == other.mNodeId && mEndpointId < other.mEndpointId); } @@ -81,10 +81,15 @@ class DeviceManager bool IsLocalBridgeReady() const { return mLocalBridgeNodeId != chip::kUndefinedNodeId; } - void AddSyncedDevice(const Device & device); + void AddSyncedDevice(const SyncedDevice & device); void RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId); + /** + * @brief Initializes the CommissionerControl for fabric sync setup process. + */ + void InitCommissionerControl(); + /** * @brief Determines whether a given nodeId corresponds to the "current bridge device," either local or remote. * @@ -177,8 +182,8 @@ class DeviceManager void HandleCommandResponse(const chip::app::ConcreteCommandPath & path, chip::TLV::TLVReader & data); - Device * FindDeviceByEndpoint(chip::EndpointId endpointId); - Device * FindDeviceByNode(chip::NodeId nodeId); + SyncedDevice * FindDeviceByEndpoint(chip::EndpointId endpointId); + SyncedDevice * FindDeviceByNode(chip::NodeId nodeId); private: void RequestCommissioningApproval(); @@ -193,8 +198,6 @@ class DeviceManager void HandleReverseOpenCommissioningWindow(chip::TLV::TLVReader & data); - static DeviceManager sInstance; - chip::NodeId mLastUsedNodeId = 0; // The Node ID of the remote bridge used for Fabric-Sync @@ -207,7 +210,7 @@ class DeviceManager // This represents the bridge within its own ecosystem. chip::NodeId mLocalBridgeNodeId = chip::kUndefinedNodeId; - std::set mSyncedDevices; + std::set mSyncedDevices; bool mInitialized = false; uint64_t mRequestId = 0; diff --git a/examples/fabric-admin/device_manager/DeviceSynchronization.cpp b/examples/fabric-admin/device_manager/DeviceSynchronization.cpp index 092c2505d1..9274b98d4a 100644 --- a/examples/fabric-admin/device_manager/DeviceSynchronization.cpp +++ b/examples/fabric-admin/device_manager/DeviceSynchronization.cpp @@ -142,13 +142,16 @@ void DeviceSynchronizer::OnReportEnd() void DeviceSynchronizer::OnDone(app::ReadClient * apReadClient) { + ChipLogProgress(NotSpecified, "Synchronization complete for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + #if defined(PW_RPC_ENABLED) if (mState == State::ReceivedResponse && !DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) { GetUniqueId(); if (mState == State::GettingUid) { - // GetUniqueId was successful and we rely on callback to call SynchronizationCompleteAddDevice. + ChipLogProgress(NotSpecified, + "GetUniqueId was successful and we rely on callback to call SynchronizationCompleteAddDevice."); return; } SynchronizationCompleteAddDevice(); @@ -206,6 +209,8 @@ void DeviceSynchronizer::StartDeviceSynchronization(Controller::DeviceController mNodeId = nodeId; + ChipLogProgress(NotSpecified, "Start device synchronization for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + #if defined(PW_RPC_ENABLED) mCurrentDeviceData = chip_rpc_SynchronizedDevice_init_default; mCurrentDeviceData.has_id = true; @@ -272,6 +277,7 @@ void DeviceSynchronizer::GetUniqueId() void DeviceSynchronizer::SynchronizationCompleteAddDevice() { VerifyOrDie(mState == State::ReceivedResponse || mState == State::GettingUid); + ChipLogProgress(NotSpecified, "Synchronization complete and add device"); #if defined(PW_RPC_ENABLED) AddSynchronizedDevice(mCurrentDeviceData); diff --git a/examples/fabric-admin/device_manager/PairingManager.cpp b/examples/fabric-admin/device_manager/PairingManager.cpp index 8474d78f02..8d985ac553 100644 --- a/examples/fabric-admin/device_manager/PairingManager.cpp +++ b/examples/fabric-admin/device_manager/PairingManager.cpp @@ -285,6 +285,12 @@ void PairingManager::OnPairingDeleted(CHIP_ERROR err) void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { + if (mPairingDelegate) + { + mPairingDelegate->OnCommissioningComplete(nodeId, err); + SetPairingDelegate(nullptr); + } + if (err == CHIP_NO_ERROR) { // print to console @@ -308,12 +314,6 @@ void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) } ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err)); } - - if (mPairingDelegate) - { - mPairingDelegate->OnCommissioningComplete(nodeId, err); - SetPairingDelegate(nullptr); - } } void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioningInfo & info) diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index 05fb949224..f59a2729db 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -55,7 +55,7 @@ struct ScopedNodeIdHasher } }; -class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate +class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate, public IcdManager::Delegate { public: void OnCheckInCompleted(const app::ICDClientInfo & clientInfo) override @@ -96,6 +96,33 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate } } + void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) override + { + if (mNodeId != deviceId) + { + ChipLogError(NotSpecified, + "Tried to pair a non-bridge device (0x:" ChipLogFormatX64 ") with result: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + return; + } + else + { + ChipLogProgress(NotSpecified, "Reverse commission succeeded for NodeId:" ChipLogFormatX64, ChipLogValueX64(mNodeId)); + } + + if (err == CHIP_NO_ERROR) + { + DeviceManager::Instance().SetRemoteBridgeNodeId(deviceId); + } + else + { + ChipLogError(NotSpecified, "Failed to pair bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + mNodeId = kUndefinedNodeId; + } + pw::Status OpenCommissioningWindow(const chip_rpc_DeviceCommissioningWindowInfo & request, chip_rpc_OperationStatus & response) override { @@ -146,13 +173,14 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate if (error == CHIP_NO_ERROR) { - NodeId nodeId = DeviceManager::Instance().GetNextAvailableNodeId(); + mNodeId = DeviceManager::Instance().GetNextAvailableNodeId(); + ; // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); - - DeviceManager::Instance().PairRemoteDevice(nodeId, code.c_str()); + PairingManager::Instance().SetPairingDelegate(this); + DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str()); } else { @@ -224,6 +252,8 @@ class FabricAdmin final : public rpc::FabricAdmin, public IcdManager::Delegate Platform::Delete(data); } + NodeId mNodeId = chip::kUndefinedNodeId; + // Modifications to mPendingCheckIn should be done on the MatterEventLoop thread // otherwise we would need a mutex protecting this data to prevent race as this // data is accessible by both RPC thread and Matter eventloop. From 18425eb9dbaaf3feaf0bbf718a4e25062d3e4bde Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Fri, 15 Nov 2024 20:04:59 -0500 Subject: [PATCH 030/219] fan-control-server: Fix FanMode circular callback issue (#36515) Similar to what was done for Speed and Percent, this PR fixes a bug where a FanMode could result in a circular callback. For example, setting the FanMode to kAuto, could trigger this issue. --- .../fan-control-server/fan-control-server.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 7ece1a1b57..2c30c9c6cd 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -89,6 +89,7 @@ bool gWriteFromClusterLogic = false; // Avoid circular callback calls when adjusting SpeedSetting and PercentSetting together. ScopedChangeOnly gSpeedWriteInProgress(false); ScopedChangeOnly gPercentWriteInProgress(false); +ScopedChangeOnly gFanModeWriteInProgress(false); Status SetFanModeToOff(EndpointId endpointId) { @@ -160,12 +161,16 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute switch (attributePath.mAttributeId) { case FanMode::Id: { + if (gFanModeWriteInProgress) + { + return Status::WriteIgnored; + } if (*value == to_underlying(FanModeEnum::kOn)) { FanMode::Set(attributePath.mEndpointId, FanModeEnum::kHigh); - res = Status::WriteIgnored; + return Status::WriteIgnored; } - else if (*value == to_underlying(FanModeEnum::kSmart)) + if (*value == to_underlying(FanModeEnum::kSmart)) { FanModeSequenceEnum fanModeSequence; Status status = FanModeSequence::Get(attributePath.mEndpointId, &fanModeSequence); @@ -328,6 +333,9 @@ void MatterFanControlClusterServerAttributeChangedCallback(const app::ConcreteAt Status status = FanMode::Get(attributePath.mEndpointId, &mode); VerifyOrReturn(Status::Success == status); + // Avoid circular callback calls + ScopedChange FanModeWriteInProgress(gFanModeWriteInProgress, true); + // Setting the FanMode value to Off SHALL set the values of PercentSetting, PercentCurrent, // SpeedSetting, SpeedCurrent attributes to 0 (zero). if (mode == FanModeEnum::kOff) From 61e288a1968f359a57ebd40b60197976ebec46f7 Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Fri, 15 Nov 2024 21:50:23 -0500 Subject: [PATCH 031/219] chef-fan-control: Remove unnecessary circular callback checks (#36517) * chef-fan-control: Remove unnecessary checks With the recent circular callback bugfixes done in the cluster code in pull/36515 and pull/36489, we can now safely remove unnecessary checks that prevented the circular callbacks in the app side. * remove unused includes/imports. --- .../chef/common/chef-fan-control-manager.cpp | 35 ++++--------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/examples/chef/common/chef-fan-control-manager.cpp b/examples/chef/common/chef-fan-control-manager.cpp index 7c2aec389e..42555e8052 100644 --- a/examples/chef/common/chef-fan-control-manager.cpp +++ b/examples/chef/common/chef-fan-control-manager.cpp @@ -207,11 +207,6 @@ FanControl::FanModeEnum ChefFanControlManager::SpeedToFanMode(uint8_t speed) void ChefFanControlManager::SetPercentCurrent(uint8_t aNewPercentCurrent) { - if (aNewPercentCurrent == mPercentCurrent) - { - return; - } - ChipLogDetail(NotSpecified, "ChefFanControlManager::SetPercentCurrent: %d", aNewPercentCurrent); mPercentCurrent = aNewPercentCurrent; Status status = FanControl::Attributes::PercentCurrent::Set(mEndpoint, mPercentCurrent); @@ -224,12 +219,6 @@ void ChefFanControlManager::SetPercentCurrent(uint8_t aNewPercentCurrent) void ChefFanControlManager::SetSpeedCurrent(uint8_t aNewSpeedCurrent) { - if (aNewSpeedCurrent == mSpeedCurrent) - { - return; - } - - ChipLogDetail(NotSpecified, "ChefFanControlManager::SetSpeedCurrent: %d", aNewSpeedCurrent); mSpeedCurrent = aNewSpeedCurrent; Status status = FanControl::Attributes::SpeedCurrent::Set(mEndpoint, aNewSpeedCurrent); if (status != Status::Success) @@ -245,11 +234,8 @@ void ChefFanControlManager::FanModeWriteCallback(FanControl::FanModeEnum aNewFan switch (aNewFanMode) { case FanControl::FanModeEnum::kOff: { - if (mSpeedCurrent != 0) - { - DataModel::Nullable speedSetting(0); - SetSpeedSetting(speedSetting); - } + DataModel::Nullable speedSetting(0); + SetSpeedSetting(speedSetting); break; } case FanControl::FanModeEnum::kLow: { @@ -291,20 +277,11 @@ void ChefFanControlManager::FanModeWriteCallback(FanControl::FanModeEnum aNewFan void ChefFanControlManager::SetSpeedSetting(DataModel::Nullable aNewSpeedSetting) { - if (aNewSpeedSetting.IsNull()) - { - ChipLogError(NotSpecified, "ChefFanControlManager::SetSpeedSetting: null value is invalid"); - return; - } - - if (aNewSpeedSetting.Value() != mSpeedCurrent) + Status status = FanControl::Attributes::SpeedSetting::Set(mEndpoint, aNewSpeedSetting); + if (status != Status::Success) { - Status status = FanControl::Attributes::SpeedSetting::Set(mEndpoint, aNewSpeedSetting); - if (status != Status::Success) - { - ChipLogError(NotSpecified, "ChefFanControlManager::SetSpeedSetting: failed to set SpeedSetting attribute: %d", - to_underlying(status)); - } + ChipLogError(NotSpecified, "ChefFanControlManager::SetSpeedSetting: failed to set SpeedSetting attribute: %d", + to_underlying(status)); } } From 10a518b8c60702a32767530cd86ec60e0041bbc8 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Mon, 18 Nov 2024 16:20:05 +0200 Subject: [PATCH 032/219] [Telink] Update Docker image (Zephyr update) (#36530) * [Telink] Update Docker image (Zephyr update) * [Telink] Update Docker image (Zephyr update) --- integrations/docker/images/base/chip-build/version | 2 +- integrations/docker/images/stage-2/chip-build-telink/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 2546ff1921..6df5517b7e 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -91 : [Ameba] Update matter timers and add more examples +92 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index 2b84323d44..b286bb8a74 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -18,7 +18,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=f762f1a1027284e63e338e6d83deeade62f355b0 +ARG ZEPHYR_REVISION=d88a47760dd4c7e57dfcc83e7c5856a9cea88fc1 WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install --break-system-packages -U --no-cache-dir west \ From c0979245507a873fb906e2815294025ecad8b1f5 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Mon, 18 Nov 2024 12:29:50 -0500 Subject: [PATCH 033/219] Wrong title on the ST index (copy/paste error) (#36529) --- docs/platforms/stm32/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/platforms/stm32/index.md b/docs/platforms/stm32/index.md index 7b0d56ce3e..dbe427e82e 100644 --- a/docs/platforms/stm32/index.md +++ b/docs/platforms/stm32/index.md @@ -1,4 +1,4 @@ -# ESP32 +# STM32 ```{toctree} :glob: From 9eed8b421677dea916edaf143e31837edb6971ca Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 18 Nov 2024 15:10:41 -0500 Subject: [PATCH 034/219] Add a helper function for getting P256PublicKey from MTRKeypair. (#36520) That way we are not ending up with multiple copies of finicky code. --- src/darwin/Framework/CHIP/MTRCertificates.mm | 19 +--------- .../CHIP/MTRDeviceControllerFactory.mm | 19 +--------- .../Framework/CHIP/MTRP256KeypairBridge.h | 7 ++-- .../Framework/CHIP/MTRP256KeypairBridge.mm | 35 ++++++++++++------- 4 files changed, 28 insertions(+), 52 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRCertificates.mm b/src/darwin/Framework/CHIP/MTRCertificates.mm index 7dcec96cba..510bd3a53a 100644 --- a/src/darwin/Framework/CHIP/MTRCertificates.mm +++ b/src/darwin/Framework/CHIP/MTRCertificates.mm @@ -152,24 +152,7 @@ + (MTRCertificateDERBytes _Nullable)createOperationalCertificate:(id + (BOOL)keypair:(id)keypair matchesCertificate:(NSData *)certificate { P256PublicKey keypairPubKey; - SecKeyRef publicKey = NULL; - - if ([keypair respondsToSelector:@selector(copyPublicKey)]) { - publicKey = [keypair copyPublicKey]; - } else { - publicKey = [keypair publicKey]; - if (publicKey) { - CFRetain(publicKey); - } - } - - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &keypairPubKey); - - if (publicKey != NULL) { - CFRelease(publicKey); - publicKey = NULL; - } - + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromMTRKeypair(keypair, &keypairPubKey); if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from keypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index e287ef0446..ce208690b1 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -819,24 +819,7 @@ - (BOOL)findMatchingFabric:(FabricTable &)fabricTable } else { // No root certificate means the nocSigner is using the root keys, because // consumers must provide a root certificate whenever an ICA is used. - SecKeyRef publicKey = NULL; - - if ([params.nocSigner respondsToSelector:@selector(copyPublicKey)]) { - publicKey = [params.nocSigner copyPublicKey]; - } else { - publicKey = [params.nocSigner publicKey]; - if (publicKey) { - CFRetain(publicKey); - } - } - - CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(publicKey, &pubKey); - - if (publicKey != NULL) { - CFRelease(publicKey); - publicKey = NULL; - } - + CHIP_ERROR err = MTRP256KeypairBridge::MatterPubKeyFromMTRKeypair(params.nocSigner, &pubKey); if (err != CHIP_NO_ERROR) { MTR_LOG_ERROR("Can't extract public key from MTRKeypair: %s", ErrorStr(err)); return NO; diff --git a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h index 4683326926..4f4e58e41a 100644 --- a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h +++ b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.h @@ -47,14 +47,15 @@ class MTRP256KeypairBridge : public chip::Crypto::P256Keypair const chip::Crypto::P256PublicKey & Pubkey() const override { return mPubkey; }; - // On success, writes to *pubKey. + // On success, writes to *matterPubKey. static CHIP_ERROR MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, chip::Crypto::P256PublicKey * matterPubKey); + // On success, writes to *matterPubKey. + static CHIP_ERROR MatterPubKeyFromMTRKeypair(id keyPair, chip::Crypto::P256PublicKey * matterPubKey); + private: id _Nullable mKeypair; chip::Crypto::P256PublicKey mPubkey; - - CHIP_ERROR setPubkey(); }; NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm index 03a396e27d..f124622591 100644 --- a/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm +++ b/src/darwin/Framework/CHIP/MTRP256KeypairBridge.mm @@ -36,7 +36,7 @@ } mKeypair = keypair; - return setPubkey(); + return MatterPubKeyFromMTRKeypair(mKeypair, &mPubkey); } CHIP_ERROR MTRP256KeypairBridge::Initialize(ECPKeyTarget key_target) @@ -132,18 +132,6 @@ return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } -CHIP_ERROR MTRP256KeypairBridge::setPubkey() -{ - if ([mKeypair respondsToSelector:@selector(copyPublicKey)]) { - SecKeyRef publicKey = [mKeypair copyPublicKey]; - auto copyResult = MatterPubKeyFromSecKeyRef(publicKey, &mPubkey); - CFRelease(publicKey); - return copyResult; - } else { - return MatterPubKeyFromSecKeyRef([mKeypair publicKey], &mPubkey); - } -} - CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromSecKeyRef(SecKeyRef pubkeyRef, P256PublicKey * matterPubKey) { if (!pubkeyRef) { @@ -165,3 +153,24 @@ return CHIP_NO_ERROR; } + +CHIP_ERROR MTRP256KeypairBridge::MatterPubKeyFromMTRKeypair(id keyPair, chip::Crypto::P256PublicKey * matterPubKey) +{ + SecKeyRef publicKey; + if ([keyPair respondsToSelector:@selector(copyPublicKey)]) { + publicKey = [keyPair copyPublicKey]; + } else { + publicKey = [keyPair publicKey]; + if (publicKey) { + CFRetain(publicKey); + } + } + + CHIP_ERROR err = MatterPubKeyFromSecKeyRef(publicKey, matterPubKey); + + if (publicKey) { + CFRelease(publicKey); + } + + return err; +} From 8b4d17f2b22432cf5dea7e61e077b5bd386db7f5 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:16:29 +1300 Subject: [PATCH 035/219] Correct description of device controller callbacks (#36531) --- src/darwin/Framework/CHIP/MTRDeviceController.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.h b/src/darwin/Framework/CHIP/MTRDeviceController.h index 35a20c1ab4..3ad0c37ea0 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController.h @@ -98,12 +98,13 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * Then a PASE session will be established with the device, unless an error * occurs. MTRDeviceControllerDelegate will be notified as follows: * - * * Discovery fails: onStatusUpdate with MTRCommissioningStatusFailed. + * * Discovery fails: controller:statusUpdate: with MTRCommissioningStatusFailed. * - * * Discovery succeeds but commissioning session setup fails: onPairingComplete - * with an error. + * * Commissioning session setup fails: + * controller:commissioningSessionEstablishmentDone: with non-nil error. * - * * Commissioning session setup succeeds: onPairingComplete with no error. + * * Commissioning session setup succeeds: + * controller:commissioningSessionEstablishmentDone: with nil error. * * Once a commissioning session is set up, getDeviceBeingCommissioned * can be used to get an MTRBaseDevice and discover what sort of network @@ -132,11 +133,13 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * Then a PASE session will be established with the device, unless an error * occurs. MTRDeviceControllerDelegate will be notified as follows: * - * * Invalid connection information: onStatusUpdate with MTRCommissioningStatusFailed. + * * Invalid connection information: controller:statusUpdate: with MTRCommissioningStatusFailed. * - * * Commissioning session setup fails: onPairingComplete with an error. + * * Commissioning session setup fails: + * controller:commissioningSessionEstablishmentDone: with non-nil error. * - * * Commissioning session setup succeeds: onPairingComplete with no error. + * * Commissioning session setup succeeds: + * controller:commissioningSessionEstablishmentDone: with nil error. * * Once a commissioning session is set up, getDeviceBeingCommissioned * can be used to get an MTRBaseDevice and discover what sort of network From 83828f5878517064fb48029ebcce09852c4d4555 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Mon, 18 Nov 2024 15:37:28 -0500 Subject: [PATCH 036/219] Update Coding style documentation (#36275) * Update coding style guide - removed most of the motivation sections as it was somewhat repetitive and made the doc quite verbose - removed the drawing because it doesn't match the SDK implementation in reality - removed C discussion - I don't think we have any - added python versions. Didn't add the other languages because I dont' know but other folks can easily add a follow up - added sections on + formatters + anonymous namespaces for internal stuff in cpp files + singletons + std containers to heap allocation sections + CopySpanToMutableSpan + std::optional + python section - removed the code samples from heap allocation because it implies that people show re-implement these things when the preference is to use the provided support classes - removed the version table - we have git history. * Move coding style into main style dir * Use md since that's why the doc wasn't included * Restyled by prettier-markdown * add new words to wordlist * Add clarification about heap allocation * Add clarification about code removal * add isort ref to formatter table * add ruff * use links * Apply suggestions from code review Co-authored-by: Boris Zbarsky * address review comments * Add link suffix toml to wordlist --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .github/.wordlist.txt | 11 + docs/style/CODING_STYLE_GUIDE.md | 172 +++++ .../coding/CODING_STYLE_GUIDE-figure1.png | Bin 97045 -> 0 bytes docs/style/coding/CODING_STYLE_GUIDE.adoc | 721 ------------------ 4 files changed, 183 insertions(+), 721 deletions(-) create mode 100644 docs/style/CODING_STYLE_GUIDE.md delete mode 100644 docs/style/coding/CODING_STYLE_GUIDE-figure1.png delete mode 100644 docs/style/coding/CODING_STYLE_GUIDE.adoc diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index a5dee8881f..c43d780c0f 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -41,6 +41,9 @@ AFL AIDL algs alloc +allocator +allocators +Ambrose Ameba amebad amebaiot @@ -317,6 +320,7 @@ cryptographic CSA csg csrrequest +cstdint csu csv ctl @@ -440,6 +444,7 @@ DNSStubListener docbuild Dockerfile Dockerfiles +docstrings Don'ts DoorLock DoorState @@ -565,6 +570,8 @@ FlowMeasurement FluorideConcentrationMeasurement focusable forkpty +formatter +formatters FOTA FreeRTOS FreeRTOSConfig @@ -731,6 +738,7 @@ IPython ISCAN isHexString isLowerCase +isort isUpperCase itemName iterable @@ -878,6 +886,7 @@ MediaPlayback MediaTek MEI mem +memcpy memdf MemMonitoring menuconfig @@ -933,6 +942,7 @@ mv MX mydir MyPASSWORD +mypy MySSID NAMESERVER NAMESPACE @@ -1442,6 +1452,7 @@ toJson tokenization tokenized tokenizer +toml toolchain toolchains topologies diff --git a/docs/style/CODING_STYLE_GUIDE.md b/docs/style/CODING_STYLE_GUIDE.md new file mode 100644 index 0000000000..bba6ef4ffa --- /dev/null +++ b/docs/style/CODING_STYLE_GUIDE.md @@ -0,0 +1,172 @@ +# Coding Style Guide + +_Revision 6_ _2024-10-28_ + +This guide provides a small set of code guidelines used in the SDK. This guide +reflects the currently accepted style practices for the SDK and is subject to +change. + +The SDK was seeded from multiple different projects and contains contributions +from many different companies and the SDK code therefore uses several different +coding styles throughout the code base. Stylistically, code should attempt to +conform to the dominant style of the code being modified, while also adhering to +the guidelines below. + +## Language standard + +Code in the SDK conforms to the following standards. Changes to the C++ standard +happen relatively infrequently. Changes to the Python version are more frequent. + +| Language | Version | +| -------- | ------- | +| C++ | C++17 | +| Python | 3.10 | + +Product-specific software may elect to use later standards in their own work. + +## Coding Guidelines + +### Common + +#### When in Rome + +The most important convention and practice in the Matter SDK repo is "_When in +Rome..._", per the quote below. + +[quote, St. Ambrose] + +--- + +If you should be in Rome, live in the Roman manner; if you should be elsewhere, +live as they do there. + +--- + +Your extensions or fixes to existing code should match the prevailing style of +the original code. + +If you find the conventions so foreign or otherwise confusing, it may be best to +let whoever owns the file make the necessary changes or seek the counsel of +others in the group to find out what the right thing to do is. Never just start +changing code wholesale for personal reasons without consulting others first. + +#### Commenting Out or Disabling Code + +Unused code shall not be disabled by commenting it out with C- or C++-style +comments or with preprocessor `#if 0 ... #endif` semantics. Unused code should +be removed. + +#### Auto-formatters + +We use the following auto-formatters on code: + +| Language | Formatter | Style File | +| ----------- | ------------------ | ------------------------------------------------------------------------------------------ | +| C++ | clang-format | [.clang-format](https://github.com/project-chip/connectedhomeip/blob/master/.clang-format) | +| Objective-C | clang-format | [.clang-format](https://github.com/project-chip/connectedhomeip/blob/master/.clang-format) | +| java | google-java-format | N/A | +| Python | pep8, isort, ruff | [.restyled.yaml][restyle_link] (command line), [isort][isort_link], [ruff][ruff_link] | +| YAML | prettier | None | +| JSON | prettier | None | +| markdown | prettier | None | + +[restyle_link]: + https://github.com/project-chip/connectedhomeip/blob/master/.restyled.yaml +[isort_link]: + https://github.com/project-chip/connectedhomeip/blob/master/.isort.cfg +[ruff_link]: + https://github.com/project-chip/connectedhomeip/blob/master/ruff.toml + +All pull requests run formatting checks using these tools before merge is +allowed. Generated code is not run through restyle. + +### C++ + +#### Use C++ _cstdint_ for Plain Old Data Types + +Standard, scalar data types defined in _cstdint_ should be used for basic signed +and unsigned integer types, especially when size and serialization to +non-volatile storage or across a network is concerned. + +Examples of these are: `uint8_t`, `int8_t`, etc. + +#### Avoid top-level `using namespace` Statements in Headers + +By doing this, you are effectively forcing every other module that includes the +header to also be using the namespace. This causes namespace pollution and +generally defeats the purposes of namespaces. Fully-qualified symbols or +namespace blocks should be used instead. + +#### Classes / objects not exposed in a header should be in an anonymous namespace + +If a cpp class defines a class or instantiates a static object, it should be +enclosed in an anonymous namespace. + +``` +namespace { + // CPP internal defines go here +} // namespace +``` + +#### Singleton use + +The decision to use a singleton class should be considered with care. Do not +default to using a singleton for ease of writing code. + +If the class truly should be a singleton (ex. if it is controlling access to a +hardware resource) + +- The standard function name for accessing an SDK singleton is GetInstance(). +- Singleton classes should delete copy and move constructors + +#### Avoid Heap-based Resource Allocation and auto-resizing std containers + +Heap-based resource allocation should be avoided in the core SDK for common code +that may run on constrained embedded devices. This includes any container +element in std that automatically re-sizes itself at runtime (ex. vector, string +etc.) as these re-size operations are often large and can lead to memory +exhaustion and fragmentation on embedded systems. + +Heap-based allocation is allowed for controller code and is at the discretion of +platform vendors for platform-specific code. + +##### Alternatives + +In either case, recommended resource allocation alternatives are: + +- In-place allocation and initialization +- Pool-based allocators +- Platform-defined and -assigned allocators + +[CHIPMem.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/CHIPMem.h) +provides support for platform defined allocators. + +[Pool.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/Pool.h) +is the Matter SDK pool allocator implementation. + +#### Prefer CopySpanToMutableSpan over memcpy when using spans + +See +[Span.h](https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/Span.h) + +#### Prefer std::optional to CHIP implementation in newer code + +The Matter SDK Optional.h was implemented when the Matter SDK was C++14, but +newer code can use std::optional, which offers some benefits over the Matter SDK +implementation (ex. std::optional is trivially destructible if the underlying +type is also trivially destructible) + +### Python + +#### Type hints + +Use type hints on function definitions for public APIs. + +#### Docstrings + +Docstrings should be included for all public APIs. + +#### mypy + +The current python code does not yet pass mypy checks, but we are working +towards this goal. The more compliant new code is to mypy, the better. diff --git a/docs/style/coding/CODING_STYLE_GUIDE-figure1.png b/docs/style/coding/CODING_STYLE_GUIDE-figure1.png deleted file mode 100644 index d8603de93c6067f6e2dc1026d72d4c66a642561f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97045 zcmeFZX*|?#_%>XTv7`}Eq=~YxWh)uWi0ow>Yp7&5BwJ(6S}NHIVNi^*WtTNlw(Kev7NJTLC&#r=8SJoBRFJ2TgQF2{MC=Osw}mI5^;6XlU3N2rw)$de;VatQ6m{R@@U9@>+!)k(@C4cjWDr%7MjO%7xr<<_*k z5fqF%&Bwr}sKo7i{2jq2qgOUL@*M_o->SzqU-lFqzqWy1hTKPg!o^dUI-ckhzxTGR zNmI@&pLZGB+L_*docLHswITL_d3fv{{IsLDkfZt3*Jdl zgeQtqz3=b&#R^-z(yw@&$IZ__Da`t(B^Z9?p6Z)x9cxQN17BZX`SkLF^l+j5$gpi+ z{<~Y-agy%E^rt*>i1Rq;t%2mC{Qc$ON)D&TEj}a=Tye`A@ve!fseaVnqM4c5#@^D_ zR7-rzm*8_PVV4vZ*1vzh-&O7HZCEp!Yuvu!JpZk)e!Cfu>k=)!bSWouv z7Fx0;`%7KA^a-5C6tfbB`veK(WLAF;&YxQ=t@o`-_}!mB#>BLXSQ>a?WW+T|NhPZlN5m!ZJom@oW$JSll~pPsCq_R8u$7l`m``zu0MHfo{ z%xmo~l20Qb&C&ds9GBOw-$BZ9)lBsMj{^zLK89%Ad3NejmSX$bQIszG6Mx^FOxcfW z&gz8R0qum*r2f$u2-O*Z!jKLTa(OSWD$h3&kZ_tMhq5Xgd=73tnYG>l@vp2gskHh1 zn0i)V-jd&S>JHL3O#mC4Li(gU1ia~&X<^u0`XeQf~$eiHnPijk$I)+)0)54k1}*Yj+|Y!i&mkdy@>MQ63jn>~-33-pgQOeYKUj_pX*5c72>aD^1>)wCTf?I4;}V0BWz?fO@Riw+mt4V77k-vgigaRkK0 z(0JMomGw9+51&W3KZ$}U&sns-(MK6NIOO$}yV_Sy`0R`QyIB*6I}=I&HD?zc~cExmyqH2cYdz?yCn6iXw2*ht@K+(DR+Mn zCey$>9j-UxjyH3gPoF;BJHU2~?8I4hQEJ(esL06PX1AB&_@*Z1F0kC~vr6PKm$xT< ziY*>I&{hhlsDQigr*T1d1|kQc7o-NgUeO-kdU+?8gyLAx@pX}Qk*8T%d|JlFb}ozk zX7*rWo4PRns!!%EaiSZ9!4HmVw{D#Tdwg)zMA4KJgl;SjSo9a8Y$Ci$)S^h03BXqv zvQynrJjCf3@VZ@+!JhwNB@)2W8XQWW~+A)Y?14M`waEanB3$H74?QYj~ z2Y%s#8WdXIwVCj~H!?q-Br`e8BfPC>?1$%Knj-rc4b zU}?!@!79N@7jybCVrUFyAXtf^QhS=(Im1}Y)N?nffc+2u7#RZQCi)@pSy&z@8(E~2 z^_&k6)txrdq1!@;kXd}LNj5bd(hBpOgu*}2GNt$Iqz|nJlB`Y{#-)8+$hw>BoQSI2 zA%0+sg17hGZt2tMjEIf3GH*)^hATdStAEc;66ntS*m!Im9!f*LjAj|bm|Cqu*Enhp;+bkdsOhZQf zb4{UDSJvGKxrgC3l2adjNT$h;N#5*4WC~j*Es2Thb$1`f3;xx0MM^Ygg3F`v+J2uV zySVa$s1qO9XKR~Fi|!<}w&TP{fM74UIEU-rpW8^cCR@}hnH7)Hn*@kxeoq;~e&0>9 zKc~}<-LO9g{axAijKH18t$SMB9hMDeCEW_Mbu4)ZnBw-wE@~&%wbV|{OH56*C5_xw z5xMx+USb`8PCF=2vR_vwMAhZq`Oujt>P+D|W7c<)z%%eIRzJ$Q{ENNYn+JYN=_uus zQ7@IGX7Zz<-DapRsdcT*#gXc2qhq(XL%G^TD5Jc~J0C{P&F9Pc8=oOy_L8km&b`2} zU)-%^h%1AuAD0b*NiMj`jjNmHN^PIJ_7G!~b44TgRM=mX$tDNG+8VBw?5Z?y=f!Z5 zFWRW>nT;bGO55dKAuO8&ohJ@fMZV>6PMKLm z2R+JTzt*RCx5w2a+-&QX=$gAM(2N5mMbkK2mie^)P$=WSL+=0LiC!~_d$Y7**#NB6~|ENqmYWWv?y1NldXIt# ztmw-7(7Ga-uQ`lPd1TVo3{9D!5K1p6ZoHkGV>?%f^RUov|Ud>qLEG-3?%Ki;~-~ zFV`546k0_Xu_AcySe7qc_1tn2wjYLXSCsAk82hxbS7t;p4QxLyjd7-G2~9;w`Sq<* z#KLajkYp|sw=#2pv~k{pM%r?tW%=Cf@E8&@V<9geFx#7#8bzU8 z7v;qJ%f(`OfN0^>k;m5-2k=>Xd9}l7Y(^z2WU7hqK1vED2>ZKayj4m0_AHwH1#K6;dO;-Qw+;2LwKt7LU%phnj%HPMIk;>r{3 zG;HVA;5m?I;poqCqBaYQaraYkOeNYG5hwPZA1|@Za5t_bmYy=2?z*KHT*5IEKp4)7?+Z+ zFRaSQV&zkW?U1g;&ZmgS-m*(+7qGH-8$wx;YP2>Hkhoe*ok0jP;D!i6rfoJ&?&pnM zr1b7`E|50ZJd^9UZ|7KAYzT~rb=%AHpe2ut7Oi#-jU3F9(ibOOD5%Cyei7aSRD(NGqGjOkk-SsTATjU>S`$6x(-jGBrtti=;r5AWMYcDuchTe$8-E<-f050>bcu3(7?u52GJtx2M~Qzqr-Lx!AF_(L9f!*#c5xWS z{kH*!&HwT~#CE?Uy@LV&3#1Mn{~PY$5e)S|f>KL$z|^d^ojiZNVk9yJKx^ua!SfO> zBH4x|UeX;7jqEWMBQ$N9>tPfmWLXN#yr?aa2>uveMzw+_>{lA;@x5?kI6f{3<@+YwUZ$JOUmjCp8uq}V~`_IUK+W%S7 zVQ~AWA7Ya~?+?!IppSq0{DYbP_ip|f=Kp-Q|E=aPFZp+c2Lu1J1OLg`e?$M@ob8c+ z7JV?6e^z+#{NFVGSgHS8v;Fso4u<~!r}obd{Esq<>iY|;2%Kx$2Ry~Yw!a!a$*7M^K<%*)td(PJSMA7eBF+Scj7vWzSHUroMz`O@0d z@YGh$>%IbuO9w`d*ryDvo56i^NfgljMHc4MUt>)L%iCl72!uxyh!b?wl2c<(FNjsT zZ;HKO;0Il18I^z2*3r2Lz0U>JmQ2kXtn%Cj-R1!{*m0ua)ITcehe@6&DlCjlgit7p ztf7;xIrxINam7TC==OI>N7kbtfFds@$T+U-<~?4yKY?JT4K}TR73;oSiC2AnIoTk~ zq#A~%fuJ#7u&y*U2@4OE?}ws(IDOKWz`*q1eUV1;*Z`owzd`@tGQrU zVkZx)L%<%GnZ*tc4my6>EOVa!*M#{7GBuz^suHZIz%0vLm+fvPT>o4cK-%c1ev!Gf z`d>y6L7g0KN2Gt*I67X7SZR*(kW3(UCu=}p&;kPY|9X}2oT#Y{pi%=n)~eqsFr(>0 zj8l?qh{QO554K(8)C6Jy1P9DL&#A`74KoG)=W?jeiM=U^OpqN2gXG;75kvKBqhfEK zVP|J23I++XM~-R4u-Nur68xFV=i}_}L6lL92fj}nyvMD)FpZ14j@2eo%On-^JO@sKh28D`tCr zvp8dt`d`7Hd8S;k`NkIkQX~O27=&L|sRm=^mKw{!%1)eqaYj(=!-o$lSp zkvnA|rQWD-c~vYg?uu!kq~Qxx)2ZzU{D4^_Im7Fc#%Wa9Xu1j907aVLmL z7-{=O&KaTLLsLK$)=fOJ%ZJXAAu=5m>|sGP@@R^>pae*Vi86McEa!9NF6clUEk#vA}SBQKb{Ps-fC4 zusW%ZvqBG^Wni(`Vib@e^R2a6AbP5X?c+_&&6%ip3D+DjIFUpA<4F-BDx$bm@1L=T z(bg|VG=o9f5m&6n%l}^6)MEm1^JXB(uSqJv0QY<9UvaU-u2#?rCj|AF?P}}0w!c~< z>PgpWHX2Gw%7uz;^y*Zf6;+(FFZ@|0{H(NBMPpM_zDkI->g{;3mYfP2fv^9r!8$04 zSGV7a5+{3B)H+go8-JFJ|)BDZnfnI|8WA#JzdLEK$Wy z2UPcqH5KuYh^N5<)x(9oV+w=t^*s9{*LA9}nXHo51|IR%`bciAP>6$~2#{ynt~!9q zbYHNmM6*DFNz$H7wj%1Y=l=kZ$G#A=U0muBa^8v{(gL)^iL;kKeod4d02FtT0kf3H zS)y^H*)s0+f{cy31I_tYU=TMlc}UgXhC*eptzRV%q2s)DuxQ}UF1=dr?9}{M z`z&RtC$xPqH@(WL{`dvN8`@w%-NrXYaO$d=v^%Hq*V$*>R5K(VD@edP^ng!@Dt9>M zvy0LEhUPIj&24QZDq`00wAuOv=B&`~-K!Y;k*bZ=^J2EIhoXTZM+=$&#rA`@mo5QL zk5R%UE8+Pi?lcDhL?HZG2>hDk)JvoA?rfHn`9BBD_5t2*O$7{S-n+qDFhJL*&Iu7% zHZu83GpKICW>%9f-#Z4}GJ!={xGOR$s&9@7Uq23fU~!aKgI{m6Uy%*o`c1F;1*lqm z$7|?ye#jw_-mZA)2m-0k;Truw#x5SD2fz-6T4Luuu8Th;+y%beg^2_VMUV;6@+PT< ztM@3h)87n*Xk6eeupg1)wY)>8?m3L$wK?2{Bf;7*knjEC53?cS24Y5czXRWAfKni8 zs9uqE)a-C&`R*I%n>rLafZ9RDUL|&ZxAl$qhT}KwHvmDzS#_l;k@wCqO(1M1Yk-?v z=>29^4d>$Gy1Y8o@+WL!iJkPhKmH}yD9-%;@$a$RPapU-wpF1J0wXF!08s*ZE6@cAuOh<2?xm0W(~jei zXF?$>hBytavuyP|yuA9jQ-?ig07Y%he$bQ<)&o*DEt9}Msfpwl6tr|_Xk|v{YK6Zu z#lXmkM@_OW(QYySz~}AjXgh5|Qm}^;K51;&`kG&|^b~)^DG#n5g?PMr4H!O?l;mF{ zV@R?b2#_Ff%=D14fyl2opNj_;I5WUEzdD`1l_PP&DmqTAUK(ar>=YSU(KBk)9?kgC?BIA8c{amTd9%u~jwQ`&$tA}S^e_k@q3*_ekz z)zqT~zq0K7hgHB`+=7)N8LXeL23?sztR-`cU#H4Vh!FvGNO(zeRaKeFL`m@=U@o!<3V|GI=byw6h+aPFVDtWXsuq8 z6Z_@nhDKIwfs|ABq2*wM-Weg`glaou{Hf41?r02I5CF? zs{-_54cB@B$L<#%&&FOhYdX!_qzdBrj7N({%<%6<8WUB)&2D*7H43r3(P5Q*OSX1bfh`jTfDOr8Zc}VONID%Q0KJhatH?4 zir~HFuDK|d^!7Io)sPSI^afU}mX8A9SV<>u(Qqx*B&ng+5Ep#ZU1}zg21>F66G5wY zHM(eFrY?vsGlw^Jaj3k+=pHGWMgq;!hn=MCVeW_`%$IGs&8+H}JkgGVFxk81=9Kt> zrJB6`y^q|Jh@aL}*59T_(##)a71LDrFx0lyDKi6kXGGIH1xWeTw)gmkv$AR zm3er0Y*Xc~PMhF+uBl58#r^^{UhmcbS6IyAfMM5N7oM4;Jp=%XJZPF>77bp0O9=vt z6afP;UcXp&=||1rl`xQS93lEc@IeJohXj!O3XZOE!pHFGKWbgqHbx~^`5crVJOOZo zXI#hk9l=iRUi_hCx^j?H~IZqogP?$yDaDdto6C@ zbcS*hury&1rg9Rp6WFqx3`(Zyr7d84vqM!y(e1@3!|h=tDwN?~6a{c}M7@w{Y9I+{ z{n{EUT+gAq#VC>|3+v`*{Fd)b#lZKTAY)-xB&}okY{Z(%AWp;ahiDbZCR&25sXmJJ zizGDg1mk^R+);`!5VZD7L6}Aot~*l>id>1E@TsbIONz^J0HsrowQA#sF${4qc?Smv zWQo&f;6QK9suMcv;UhJ;g$bvbE*47ZK} z`TpLVFnRy1-aN zdx^1rDbE%GZ#V50yoo$R%UQM{n|WLD&41bzZKmyu#Cw;9K{^7Wvj<8YOcNq_fzhR= zTSw#9uMva#>G}1`w!N1n_-{04&*i@Wsjq&d?IEBD1vsZuGq}O;XHGGO)*dL*giqY1 zK*0l`TSt({=3yw|W6$J2-1H_AXGB|LW1bq_EShFt&J@%vm=h)%*WikwaKKmuQWInN z?|t=hvhDkxQjdS!9i`X)Je^+51V!6*x3zoOnowu|2wNav&|FI=K948sVXB4K2S@0W zuPqrZ(LMig<*{c#vgKz`n+aYkF_85`%Rr2*x?$IwtDNU`&c$t;sH>|xdxF5*W%dgQ zB;RGh0pKm-6`0w*1#*3M5!c$ML%)K=8Csvqi~jkJ`f2~~54hYuE5aV2Wo4aKQMuHW zugX0Mqkz}|!^n6{)_ni`0yVniE?OqMgmbFoz5h=d|a96O& z$w{P|j3_^6=T99?5HKzl9*TeZ7A&asdBim@3en>OsfxGO-JvFM&sA1G%1*&X+ zqY%o&I_PMzZP&ae>3v~j-fC&FzFLsDFB6E5XRqA%Uv$K)~6`Yam~lvy@!Laf^*D6W+VXzV8)@Nm>^W{1N_BWW-rl>Bpja#e$I_VW>?I znqN8HUMzbX#`hz9+jiM2oIWJ*JC^gvnp;yveelMHX+=_h{l$^_j@_GXvWVQtQ-Zew zl@1D0ClHYuIywxcLChds-o+4U*=^Qy96(W7Sp+?Ws^K&HPjX7fC`c(tqJG#|X{s5L zU;h@N0aJ`qO}O5(bR$aMt=a&04OJy1kBR@wRzPnrX*GiP1zr0s(K54L`6k$SNF@ZC1aFR!2t`pD|r}A z)X*D;3y8n3K1sktmE;Z?SDcf9mE!q=FilTo?c;eayxQ7uhA%i13tF7mefL>a^Yp{Sb@2T&y4bXHbbfo_yu83>x$N z7?NpWh0V8j2~}NtM%9qGj0uF~o`Z3voAW4o^kDKqBvHV2fE9Irx?~w42R3)oXKE`w zJ^gCXJEj)^b-6n>3vZ3&rrBBY+z@IeVV{q(x**1(E$G`>2-Uq_+7h$#!sJ)DTV*n< z)R=lad}eBhQ<87YwIqR>3+gn|m00nED&XQs)zh~~`!yog0p8`Jw!xdEB$FOC2S67U z_c0T_kxZvdFdgz+_Wafk04fm>T2T;X7V^HlrU8PvN;rtQ*gN|bj6$4+8c8Zm_}j31 zWK3FiXyt%3J5a&{3Lw6pyv>5`A3ZO~eS5Q!)JSmEt7<`IZrY8)JA?C>YX4J<-Aj#r zA|q9igVSzphI1(VYWY;~ui>g`5QSMKa{bU%71^u{Omqz?5j@a$7U+w~RTqA#E^8P~QdL{W(3v>=e%J;4Xmr{+c_ z^+o=k*Eqt*&!8@8zI#W6al%KXDr#+WGklxVv*d#nMOd_SclQ%J=f^NkPJ;lW+>K2E z{w?-1!d*B)c8bHT5-NO~(DXr60pCcnE4&~8zE=rS>H*(2P-2gy6X%5LfQ0|_^Gi_TvPm;cU|b&(u9yOP z0mR5~AD2^w)e0aK;aA~CV@6WF?mYtKRgn<~aeTY~q>mhtjRN79aRw15|Pb z$l5cDJI$y!-8v9tAjwEjfLN0lg`7kf8z<6Jf|D2t4BD!Qa+!x@4c;nV{Zcn?^ z!#_HfAsM^v$8PNn5>;8`CH%FJ*>fWlt0wk>ZyYBeRAVe>zPdgRACpC1C=!jn0h2ou zhg0wR2?O*MD037fumq}zS}VU2$owu7EaTj_PNE2Md&6X7)EBk#rhTGO@J06JU&gZg zYzGh-14z1eDlz?R%G8s0uyux#G~N3$yF@FlBGT<+)N*Q9DG=0VE$FYVLa3Si;m?xc z>bWEdM_o(}wH|eo+*|qn*+of{KO%@oIuePKsJjOF4#4dfzcCpAf-MAg%jZ4_4K~Ub zqwfTp^Joe+knpEI7CU{zW1x^wE0Nql$eDgRG?inc|M|}T2+wkH1vvo|?>aD32+d^L zAz)(cO?E3AHeg+xzJ(2&c0?I@a<;)wvFCVM&SKdhU~0>00YT!D$?u;_ktPCkb}8!9{=bOp&|DNRekgeS5GZ&W!`;p)hMsuH^o zH%pHBxkOuUd< z4BgwT$O%MoOs~WsqqlrH*90P&lbZRs6#BjN>5`vz?vkhdtivFCo~TVb`^g}GyCwTn z*Glny4ltu5-M3*}VW^H2c_gRXZg*cls6&kh;aDFEc*I40<%A$)?Uj4Aq@WU)hWA8a z_rP;{URxqacLB9ok3_22KZ!((njva2rKP>MEZV!7CqT&k4Y(H8wy?M>M*#^T+_kp!8ZqgvLX zkY)5{W$l^lIl${=t1}i~kiY(Wi%ejOG+Z?V1ym*HZ?Wj zf)_!yz4va$%?U(SRTqv+b5%`=L`|2R=VZ85(eZWG$K5ghym``#5fC@J9Q1u-YJyCr zfbII?xGp#%Nma5z0|j*Zpu15{-hDTNb?XC@2YhQ9zh#{7X0>dW7i7}8kH$YJV#D9o?nJ0XBtZGX#{7pJJ5(zRs~FIyW6gRoy&EF7zC{x;cfJ zpRwLA(&#N?TOWI*i&86%+*_CU@igtq+i>_p%eh*5tFUu4bHxHjH#%DAC`5;%8U66F zOO>rIJMKh@p*e@fc$XS+Z(=o47sS|0{^Wbq^$Yxc!g=t_4j}7Sj0O|mAbga(MNgj7 zFLR&I(u|tGq6bQ~>s~FctvPLXU9e_8>tt}tlLy*e!0u7b^gx*pJ1zfqz;q=cnz>{1 z>YX^t&jH$zhmJ{ZvIY?O3;Mz(wh66Irl+R|ew70^%E@G~X{_{>$fNYNgF^QB#~{K# ze~^3R@dH^?L-8~@O^akCDisBOecLdU&+=I!#M)o{;i$~ONG(c>-dCr;eOZjZMc+^q zX;j^X6Kc2S&X7VKq!!{z;qB4`fS)R|m|laH(i%iF{e2_-afnj45EMN92lOzP=E4-1cCzwRI9_o900`Wf4{ZkbFeK(=Cxw)Y0RrmNu z69)&tGQ5q17}%}6I=iTn$y(ZTx^V6LjN5_=!`yR4?`>I)8Kc%)+jpIhcStY#y<;Wr z9?MOFj8bH4=&u{^K$Zy11?-jHuNz6grUBrnM!Re3{^cbj$C^<_(W(@IWo!KHgAc%O zBg4NU&sn~N7@;va;AbYn!orJrJ$fq&71dpFE~g7w9|$%0IUA=8^9M{Iu8z161ro4c z>HLHVaaDFhQzYS(3iie%$(OB-nCy@ zY+hUz6D;#@^g|501d*3$Kj5{$Fh;=Way_c_^cZmWs4Cgj8S#pDAL#mZl?d2EA+6AV#g`z501P*W4y=^pIgxE4iCQXWS7fgf*)&mMOcZzISjyzLjCu{`HD4aj@NFD% zYE5G3HK4J1u>{QR{tp&&>uE0TvZIsg@L84K5sJ@R$$GTUl?550F_4gLfB%V3jp}@q zpL1pN>Q#o>A-CMO(RJm6t(!Y$!=^6otT{g_b*kYFn@gz!RF(Dfzsk|MB{9oIkt>2k zx5)yvhVtukYK%gi`I4l)!Ks`K3Z&(U65qbj@=Yh#IQSrOA|l{hlAIhCdAQkT5xxxHyCln^qaM z35Vo9T`cEX^uzhvj;xmB9W$4I8BNNTab5@{4Tapge0Ic(U2$s57=LFk;P8;&^Z5Pn zF1~6%{MDMuL7A9mf6x}bb;H62Fh@Y7CJB3am9~9C@s@{VF4HCD(15F?Lx38+GwCy7 zSW4=AYI(V^s@nP_BMecE50-~nGS%qcCg*?H;>lPozdrD5Gm zkqkW=KD&2spd{V1)HbzBM1R<9xBErw8vBC4*nY7fYc9x(TaVsae#E=H(m$PAwT)#O zeefDy`k9ktc*X0RJdAuDp>FnRXlMIya-&8~>1y#h&b#0;jrsSwpyFwtJ#KubML!4y z)l!mk7WP^fKy+Q4WvE6M^-vMiEC3#~`>ci*{op#NU5SW@Fl`=;8l*md{WO|pyoaGM zL=J>cuR1r=@)}9h^h3E+8PFK1;|iB-@v*y_CWI=<#ZS-uB|Ip$m6pA>B`L08!S{hL zbKN(kmnfbV7DCT)z&4F<#|nPHukQ0Kewsbu=y4wuwz7y5@=I=Cl}DsZNZx)zoIA*- z`%jTB9}uZVu1Zl%UlZ(Kf&DB~7p>3GO2?tPb}aF+MrI>GVH-(A6<)G^WovK}7Z#>N z)7${HdsX0O&~)TVCSC!a&JQw>v7Mcrj>TuroT=ZH$exS(A;m$=t8`rr&%XEl*F%e? zD39%Q<_GRdZe=kIS3~Y6m3e2rN3~Qgit;D)vhx!npY}i8cD9^txVYy`oZbZD2cW z{_wvex9bbD>%}Evcu04fyX$p*TrscN=TP+{IxcAKk#A7fz}y;)DjpCrFzf zLH&F-kP&E=!oPc43DmNSu5b;@BQ+@W7KaO?(aN7q>I}6e$c&g!gljLMM{%kBCHD3q z*Gatd_psSil7L?#+y&oGXHj_n{Bdsr@n*uuU+?EnDU%D(15ze@3KT2! zH!*pGDlD;_E(UGH+q59+EA&=_r4HsG80aac2Up2v6@NQ^Ml=RV->rS?T{X|VOR{K_ zmIjQ=N;UJ|Y!!yW%#)Tn8$FV5*6hgCWYr|g(?rtf8z;3a*FZvXF)DYvzW5?mL>b7p zKFw^wtEtt@5IA|veF5LZfZR;@!+L{CvhHgdQAd(D?@hHP#D`Amews|m;q0=eBFY#j z8Yt}do!Y~%UvS}prhpqB&80n};;BFh8X6j&^#%YM9AIJ2TW`qUT&_2OVY$sgRX;#c zPw2_E>{Q5bPn&-+Rekv`kxfaWL?tTitft;`B&zA)YPcddns~{%xhxD4WQamIz6JjS z`zDHr03{5&ywL8;S7w?hR}4`1Krs_iwy^k}Ie>sVsSTiR9I1wHZ(CTfEkFMk-mKj& zq0J&*^=lUJ)w%S(U)Cx4Lx-|RZA?BdH@6ZR-A)4-ilD@BCE%q<6E3t_Q+4Qm^Z(K) z-u1|7VVoPfW~4LelXfqoUxt^@(vZk)qy?=Tp%9&HaeM54b1p1a7~vmd$%`2R&^6fn zb+c3{n_6($Wb6&GI=rcwq;j)NwGSIYWC)b&R`~BlfIBqHl9uCL+B3v5^tixx+$YL% zjL#rK96f>a83FkcH9NbU-HbHs?=iRm$h+Gwd*9EBDu_CbU+x0P?Bz$189W#1=RUC> z23Zd-^GX*@6GbArIM{f*mt}g+AnLCl=GMYxVc562yuAKNu}G5l03-8QxHPX*gR6zA z@nYF?Wp*!IQfrPsMK|-Iplx?+U05ZWFQY7x9Hb}R#(E%gt9c-$ z9T^F+J~{iPKzYMi%sA$%-Qa5)GzQ%J>b(AKZaFzh-dF5oRxUi0y!)Ecs?II_Vq5*u z@jFS&g*fWkbhDYVFN}xt(!2@dLc^{*VbySjH_KZS*JnCD?TsfqClJF{jk?IpRCL&dey`Lv z{prMPWRdZO<*F&cDR{hTdq(o|Zy9{a+e(33aSth|5}!RCEuuxvcZuz2|q z%i55@v+3oyExsOXnva14;#dv8yBNr5gQ6MM4)snCV3p$UDluEeD<`m{UKbOS!xMc8 zQ7-icQ5PJizTWGXeL3l)b0!o{K9YlDy84X{Abqd&5A+PQ;EfylC9`jdB*n2KFg~^ zb+6IU{C-W>R9c_3a8jAsl*IWmV>IE?84-7hHQv!M^)==8-1xyYDnY5{?k9hK zH@w6tZTV%e;IpcMTf4`27@hf4wGJ(5SlyMy^m^63UBNht7s{%`Uz6flO{*-fZ&pk# zn$Mou-3&NWw1d~%&&kLHp?@#Y>JsdByRuPbONTt@3}06G2~oYSRh#&!z)aesAj9^K zsp$I?sqvNZdR@_P@z)$c;CPal$JjfdR(k@6p7db`A>s6RTT z9BSKG<#xpKgYfRBZ1y%y5HEPS7)9r2-cCtoQ+BL%Ci*`Y}gq(b%h)E1r94e4lYfRUA)Gg0uTN(Z0SEC< z*T?eZs)3ya3+c@Mjc%>mu@cJ_T^un0A}C|K8@>uscW<)BeX(9w6B&%v_dFR+7Jhc+ z4r&bC*)Bdhwd}Q7jzeAl!o!ZAK6@Kj3ljE_G0zKtdyabF!yv+6FG{B^2u%okHEm6$ z%(4n@$h~$M@cQ}bf&ptf+jYQmXuZ1m@~j3bKBs(=iYV{H)vuNblg+6)B0=D`l3v;P z{3~a`$bt2}>YYi!fu^UA8%csMi7LLiYHwV$=$0FI>%C=13Yk8x zV`QJ@8$o7uZ{1+Ibo``5+R#RNl2`v7@7?vOz;kxb;^CoZI~<>GI<`BbbT!XI(U^Ly z?TEKzh0omzkO41nPH@v6SuT`I_p+anczZ?QUh)V()4*6QAN^#_j5>U2*H*}B!DaHR zSVGxuQd5*tG`TMp!NMGj&|g7W`(q!Og|qvz)S6CAT&NycNSR8%QOzrK4wU0*li}f4 zz{Hdy(-gX$%4rSQyH-LWMDD|EL6qMiU0{cr6&k4uL2;eQhPPXAb8FGf-N0Z?V4~H;|}_nwgba$&_MHR^#c;5SD;3-) zq%-Ps;}K`>gnGGr|6aL&BV3L~PVLHQAme^QqQlCPHVA?xH(q~OEFQ3~*mWP-HZGby zkrxRGXPCBOIiuzq$43~gfm{%g{#gSBKd>>`j#K+F4%VfPTlG*Y0SUD9H}LkKo-@f$ ztt*U7)sOK5`AE`GYo^6@vdvh$wk61T@~v&-(w^a64UiDg^=s`;Y-;zwb#R&HAhV|z zd23OXt&WD?%f-AG2fwwHx0vAYgXQ)T_U`+oYvK(RYl0@F+x2V;q=@c*k{X*7z4TeC z3%?qUKh3S)O}7tcK1J$KrG6pumC^Q&no3DpK3rWWqagRX#F^Qz3!?ZtrqfFGH(=l| zFMMj14{-v--@roLj|>iIqUVM_@z2w&4!bWWIL1qT0=dFiU{b!w!>}a?wdNirJ?y;) zIB;n$Ts`Dy1&D1QotF;vBARvc64~aVpeo_inlMOT zJapw6UR_G%Qr>=;@ZGs;@%iE~if47`yvx9)Do+85ahM>wxsB)_O=Ngw!r#Kh+uTk%}`y0qd;a$j;86Y^;p8c! zuGOo+$khzhmCA86k%K&IRqQ91%I0%Q*Wv1#8Ho@k6>FaKHr-_5{JDnQL~_vov;^IG zHSZUelRn1F&Uhn>oXQOY#}Us>WUxJwjjOL>I??_6w^f;>bT_xsS@G*%wle1XVTBqG zj3#_u6?ntv-KQ>$BjSBIx(bhnV07VSP%|T4u&BVY z@W&H7vP1QLTPYqBzUKDZZ>`?r{HQwjf4u999|;okDRuS=WAx}MX;Ikr{C20asKja{ zL!v`5)o>YM{&Bq|z9Lros<2Mtb3@IHD-J_5_VI~HcU46;+BY}4OsC^_woS6S@|Hwr z(yrd9mYVuv2(!%IUQNiRic`cpXM8c)`F^Ij+D9(n`?Dwg z0-*yUn8fDXh(Ve#sI~+7!Pf0Wznrqr=Y+dKw~uk2cxEf|~ z9@$~9p7%I*ae%j@YhA&UaMuVvY>Ag5$*~#u;I55?&{7-aGTjv_H@;`L)z7!OIC(qn z0_tbwufBqPJJ^VOprzbOyKru-uiCpQ3F*BkMhVZv+4aVG)fZxmE$N&doN3JuUm3lx zaawi^p6y;wO}?_Sf0j;32qyK-8*9~<=Etb>bfrCcK8jP)hbc1aB?D^s8Hd$b$2JB> z{aggcYJQ@5x9;?7_h{6WP3e^s^g`^_uXODDN+KzG>uX7>V}iV2U8zc94VQl=|LWy@ z8qbg|5tnSTR~0lV^rqzNuiy_mI7IS@sANk^#96vvPgVGj2OnZRM>rx@-$}?;+gy*^ z6E7KHXG|5JqGO1{ZjGwtG8G^|6hh}51<89>*5Icn&zDYo1UyoT0D*sbYO2UT$ugTpj zgGQgEE^IdX)sL^-%>6lG;Uzx$B7%gSN?CwxSfs~k=Fx}P;!)P{JhtEfn?zC1+!nEz z4cOf@_|CSQ5=n4SvPqn|kf50=+v?-eEv-wc_z?N4FtU+HG0H(_6IGUt^~$(FUmXH0YF3eg?hcpz4CaPK7Cl1IP)sLQTir00{%c)tp-xBt8K=giHW&CcM5}bV3BC0@)z8RrytkPBS39&K=QTuARqY1X)>dcIiu>H2%Q*mgl+_c$|wB)O( zCIPZ#c){e(^2Nt`tDo-VUhrM1tGQ$x zRU7(#`W1JJK*h{%KT}$U5bJ6_@9XNsl#c0s+tt1uv__DhgQITzts$wV*NQa_TixWV z9~wt;{})+b9T(NN^*uukJ%o}nfQX{BGz^V^grG>LA|)*~fOIOYbcb|FHw+<&bR#*0 zl*G_Iyhnfc-sgGm^UwToK4-7lXYajwt?zarRumPq|G8Gm7H@f_U`ujjmt52C++6+O za7u%}vaDs{y?MuSL09|0qQ|K7E->`l_sbvid3({%{kr|SR&c4mWc(X-?9a^UqQm2D z-*T$9eYw;$*J`J{r}YrN-eT6IjHS)E;ho@J4K=+R)Fbdnq65*3bj0X6{hGi&pL-!J;k{$gpRit9 z=)xh#0_Czg*FWBR)&(pH$-Vr`1KEb@VD`XItl(-kI{s&v-pXMQ8H5=d? z)5l7O+`rRVvXu4{566sCV7jtcy#ZYFp1k*yk%$dI6jMBciWzbPU}wZd#n zbONtDn=gBPjk`$ z*Ekyw^NTcW&wDXercoz#z_hY#V*2{PEg_}25-*wSPMAEoC}{?rV~#H7rEcc_a7EuQ zf;b2eL#TeZu;V1tE8pg~R#`S5Do>{Eb3k_(XSG=8G;J;B8q`+8vm@pLy$3yNy8k^9 zVcFM~!u#1gsZ}=vh2Z~0Bls>>x8l4;YSDrqn@gMYV*?yWuTMzEZQK);A!xo1X=Ba? z`mXYr7pm?axeI;2v|DU#A^3JlLQZY`-Z7wgUHzSzUY(sSfEIP=oh>^wtG?0%z&Vf{ zq;uD!{P8@8vi7t-Up{jKioBop1-zoArTw<>F8t|3XmXtmCEIzb@b8eky&eg>+OqQ? zk=C}kt6yl|Z1BqP$$G!G{Nn3I=iS#@Hid>v@S}d~Jg;?=gUlzzwSGSqJPloH&Ighs z!b9Zw@7poBg!OJaTLEB#E6gK6iD+1@U*CcxX1~>Zh%YM1?O6iN;R%r(cK6TEO*<8d z!rs-J&Q_;-l--(YH@(gqcT`{ob44e-jyIIt$;zTYTm7>P6QwYp!9+_O$E&!-m&)AdKQvjA+2E}?O^MxenKSRo+!xM)?moC)+Y#TnmROf3>HoVn2z zOBJZX*s_T4Lb*t;?_QnVi(Sbv&3!#sb<3AOykIreHxU1Tk?E;*pyTgSNN02fZ&ek%oarA zrdtHYAM{Uu=)d?vTFMcXT|pSA(~HeoaL+t~k4^?=87ZFOwGsjNZVAQ`fC z=qZ%hV9#~R%}6EJFqb;SWXlcOWWUj!hY9QCobZQat3{Xi=w5RJGuU~x` z_73iuQ|g~_{oWvn+o(1>XBl}L~vMaSM41@uxqz^oKipdwp5N$3>lWQziaC2H(jjKrgSwwa)G zKun6*>2QrYX{=mQgVWt+qVk)F@{>o>FJAy%A2^3=^i{=nKIcgJ6qQz|#x6UJgThOj z%ZY#qSpICBjRaz`&i2zf;Bk8b@=kMJEum(>aIx*sQGXvD*5mVL$f5W^dMM#%MVgoQ zX*1Bd5E7Z+744%x7}~y;-?#gL4ay%p=R$yIJBAo_Waq>*xNqk#mW$@il$n-!o%f`Q zO^ViDYyu5xWf;emwzBmx;ZYg~O&&V6PYgxb`%w)4;lMvT@|1~`ERQ2V{cf!`)IG%Y1r(w>ncYun& zjVfZb#;De>g~|5-bVAGidfT$cPkP+@K0~Lyf-w(kdkiMHC?sae>GgL78T5PEA3&=m z+qU0L33T(@IbX3B93grMBZPqZ8WFPegXd8>aHF|HBalUgHm3Z7{Y~mVQCZr%c zOTi4qU``eXiu2QjZd?&T?iXm;wZ$8Q^n(LbL;}Xd$aCq`yeB=Re{GpD8T(Qwg)ihL zn#>(7zu`{0a})9NW%IBNyOCXF%U8)?zuGT-xCMMJ#;B?;;~0|`<2ZR9VA_n6eS&LQ zWnfo__K<-Q$ufa95$C9fT*hxPhviKgMzH4d$&|G?O3wlNKEi?8%8cYGHHK%2aN&cu zPc}}c@T&6OM7qCSBs}~PlMoFdK&=K*8=XY~#n5dlQA6G*ReN~1@c{e^_-`K@508tR z8oT)mo&(es`BVJVy;ee2XTrFAWtt6@3JUSG9T%sSIJT2b7tIM%O_{PUqXVB$)%YB) zsRkcFV{dIW%>CTb4pX)Tps&>b7PI-!0UIU+bMA+DXSc<{cc&X3-O?WU>OL`4TxKmA z*d5(1=TT*@`A%l}ZYWSC`r?~klPXq61cUhf7;(yINR7fhW{1|xN1NI*c@6{_MIeJu z`9H7?Cv{C&eYujfU;He!e&DI4tBFs6XV+Hr4Cs)&>dkxoz2>^;(~R7yilUi285hpm zrt-+P?tsW*3RebdH;%nz!7{xk0bNl|Wsk5wU>Q#CU(Rbt7B;Gm76O^p5fmf)C*_&7 zJn=L3TR`>rio-V|^FB;QGQ`!ZcdqV|Xl-QOJn3UjIRH4AD(ux&;)C%t*WFiLYqdD+ zZ=Lc<12+9Ej62cRGd{(vNj~M$&8r>WaOt@=WTrrQ7y2lD(H1uE9`cZFkWbldHE9%E zEw>qtIE-L0|DCm$3`uVq@m?5eY3{n(`-$zC07Nrkw{&1Q7G6q8O zWMcp?9+K5{1i%Dz8^boXzkbFStzvgXQ9Skel^|&pfQ*1>Qf}zf7vcI$gmy_Go&-?%XvaCYPa~jrp>v3$O-Asl^t(RnUMyA{K(r`b zv9P8ov30W3y>!pSQM34P{WPO(U0M|YVdIxi_V9yS3cE9bQQd()KR#M#Z|oMEu9oAV z8Qpezj0Ki6YSn@6t3xX#In_TWV5Em#p>N3jXr(&t~V>+Dd%^pUt>a(mY`TlHRV(*Udz33$JVAZYA?^ ze`^D_D2uv(DC0U(mr5!7*j@5!`_17&dvf`+O9#xVhY$ zw;k2A%msb<(B;kzMJJ&^E;T-G&DcMH0EO((mojDMAC}Ti;>Mq_&;jtO zd2E4uvaD+}b)Qs(f|%*tnE>M=)Te-usrhGSBmk%f!2p1+n&BI*cFF$qEHmYKRF*b! z0GXf5{hI7ZK}Dswo0t$OSaK$jL+ z-^7TX1C0#y$sQC7HtHP;JzR7nWWaoFmlIU!SUk84pQ+hvl|p3H-7_B&eh)AK@+#`u zcR1@TR_`tvy>ex^sBwRD>Rk0^>Uga+&6vM9BgNK;?Z&Ic1J-Qr32RUn0&vowv<%lUL(xPDiXeK4{_4>2@2BkN3)(meuy+lhbMTyyfqGS$*Y` zJUd&yx|ehC!<@9K*`X$r9vzK$8&-!~)(U_R5HKDG5oIYkU)m)u8zim(yCu~0lm;n zNVjiy{G|d?z)B9rPYRSk85|%NiPZ>!}pfJYCW^M#ouwp9!jxt^2HaSpN6&M*JVXaM&IVAkz@3(kRo?RLNMn?-Y zRp;I5M8(7{Y9Uwt>nAP527Gc4payNE4`N$+f5jJFTMm{B2&2K_chf6<=%<&$^Y%Q*v^@<<+keIIW(~ zudB#Ls|#OUkye?n-w=5%h?w_Q2_^Pqw9GbF-z0emslYW)K8jS|EUNUTAFm-cZqQC& zB zzY02!8uKY|>+Gu3CQVM`wh89a3}y^W4!qJcxOGIKB|l56$SU_+;73CzNb^ zIXTXz`sYl>#y|+uS~NeE8K)~P#|j6#bwmMGu9eO^YKN$a3}jk^R(8JEL*@z7SmMTe z>K}4oIXfQVpCR7htm{qJI!W=mlQ=fNXdsi;V|0yw&-zHD_@^0SLK?`uTxb=HMYmSY&x*3r-+V?4Oo#d1SHudu%1u`JJierSdr89Y6wQbs1@5 zDNV-)vhNe_1u~Yx9W3H&)L64;%5Q9H2j8$WyF~1y0tw5as*%RFFTra=O%|wk+~&$fj;oo3q`CfManPKL2l-$L$p(F7_pN6!KDQU`*)vHhx$iIW8t4)B(4(xY5HL1Kegj|48r@DRua&bhkpM5g2!v@j+?tf<@J zkYEVg1J{>G_i$Pe{xc|yz?XCqPHD%F@Z}z4r&Jg|(h)lN$f&Y;{yYvTPJX$ffHX~ zHNEYEgdb@-o8#s@)ibJ{oZA($mhuMLE9?2yVh?gDbbQ^~<5!<{y9gyGO~=KvzL%P< zI~RLX7nHp%d=R?*q-w?Elh3mA=hJrZOkA2=`bat5&U~EteP`Cav;Cv_L4$+^+oeTG z^Reb>ZzUc(rJHcBw5NqQRL?R(vj&o6!)skNju#ToA2NtiprYrglt@eRlX&N?yhqt% zb$B$s2@dz+S}u{#tNPJ}?}u*h9}N-B8hF&9lk#YdFNO?+ z3*#T7W|D{=Y|M^x_jaCrk`!;{<9rHJF(~m&fU9k`WV%iHvG9{r#_RhGO_jI6!^?`^V9x1_ z$dO4yO;7GfjPJ=WvquG}A86E#;oK|yBUsThjk{vSQi06@Sns&riq}0&=SFJ7wu%Ksia9W;=GJQ} zq-8kJ6GraG-8w=O3$T%v&GDa%kIJqcF4#&{VCKzZzow`kcqukTy%`H4T4%t5-gPa> zE*vqmdaGh_A$VR)$o=T5q4Sv+|3thNOER3jS%aSd0+w8$hDH82q2-(VlRR+C( z1-okGuGD4|)v)BC#Um-Q6rr@WuG7aevjtAhZZj24Tdde89RacmSXNI)r6w|zKP_ff zUP~0gsns5gT*RvNEwUd4@wN`7eXOJV+#ZJl$3H4jp)2bisZK15eNIt^0@a!w4JJMt zGi|y)O~Y^{4W^4Z4e;9rL7uux^Glu>PLzdF;5}Ee3)Cx%u40d9&TeQC8%r$^D#+xY z%5$4BLXeS>Nilk#F_X~nNVQ|X50*Y9gp(nd&{8NrB=(;@>B519Ho)PE{iM0>6??;7 z1*H6v7vf3-MES8m2jj=f#QXBDnIH7UMt_`@v*ojO=5f!}b_5(!52=rGNhW`-X<^@ z)Mz*LH{?cODF?1Wz8}PtwMNDZ%8IapB=K?J1J_RboCfk%h#|` z8qz{IU|u%sedHOj+)JtuXA`v`G?Yk@f8MQDEp*}WLdQbXVR-Sr1Bwuh8c$+mo7p0U1|SCY9OkspS=v6{3Zm}|uj|Nc-(=ztxlw%*XTRNlh+ z!Mz~;n%X1me6fz zb;B#~3F#TA>zxITXZzxi+3+}zTTY~WOGKj``$6{kNO`fKl&5{~)yHSBsLFa48C6s} zH+5B^$zC15V1087wH#??zYI4WLY7@r+ot*EvlXgW@6sX{OIjqP3GpZ3p&r zd#7JD&qc(6px}(Bj5_tP`+FUQgQw@8FvmGw71~>3a5m#chs5UB66`+t0W&l%u0k_S zS7}C6LaC&8*jvm~1GbRZzn;WVs=!{^7c{pLye;>=C!t2{lrvF5Sw5qhSBvt)QMrXs zw@0;S7gkNgheTdiL8oI36BFG%qPc(*%{O^i$(t+}?>MW*q`{w53MJs$SE-F

O&Yyy?-2UyF~L0T@s}p8j{8CUxKE zD?`_Z8xAdYC`M0^0oxt?dbDDB%V`~#xI=m8OR|9Y?b&tHt9^S5ff_}F$hYi;jEro& z))fIEz#@5W@MNp}sU8QZ1{TZhRWgM7B^vblW-Z0;#jKeq1WDm{b7t zdF!nOi611AcOiIarVMW)2-3IalT*7;Y^P^`;+DhEOaBO`lqD!1iTyj+yXkx_<-5fW zaY#qNr)`klFM-w>E3m^W74+V;;OKLQE%^XQlhWY?^)`7c_n0<@dqi>3wfer@<6k>7 zMpk`%3Z2*-hQf&VLJ`w*TEB=cXX+?-*ut^^VLyXQYCr(H^HW#K2^%t^?Om#wrf^=J z0>kOvJ+2!~Na;Jge%sf_-#r`guI>rl)XD61+qfpGJu3f`Rd$I9PecMV?yfD#i88U>u0mrP|RWwL#%e?NBOg>x)yO6qpVH^e_NybOK;JjcJjW+ zTQsI65hu^w@=C-joY&^8nu4mu(V%o(X{)|X<-LURYB%d-@+(2J?Qo5D%0C8XeHIGb zMbl+iOvTA=>y=2ERAPR~e8x2DJcN_l*+O=xp%77glu8PXA57G*aDltYwe?>wv!SC*wVJZ0&0BwqV+wNbgTu4j`l}-7 zsL5@sD7**U9fr9R#d0XzzL!d!PL4p`L4X`jrz9n%4Mio?o=Y3W)z$?lV0DSfHF=Zx zli=}&SU38PErHXg>QuY-5=TfED>Glv9*hbV>%PHPwy6toQe3G}fPJZ8S=8QKY2Ib< z({-E+SUUFLGEuVm`SjYY}cEMnS4sG)=hUk28m=P*Ds@mhL_tIA9E-ilsKL6`3cN> zZnvA+J2CmbKZp32uz^-MeXw)hFaUZX_84MPMIBB9oXAt z4jbxZ1H|5Ot!Qt*ZhOa^)aBccU@|V4^m;6~`t0L$Q6(oCNU@tofk*ySG3Y~Ww@3jO z9K@tJO)f)O*ZelzzS@oP{lAHqxjg^Sl!2DN!K@*U|_GY>9xB*DU=DLd$p9bU^s6zSYLQ_3Gr4qyg#76 z9wX5VLyPUU@1eD%bkT4*j!`LhhqQLQ1Gxq!t$mSp?vlHVU!trPiCl(p^N;~WBs<~W z{=N`7Q2&zk2DF;{0#EX%KJInIzTY~}{b5G3EptG|z`H>-pb`-Nuv(P(Rj5BX**OBX z?#O)sH4VFD3?70{BHkZ6?dARm*gu{d8+vh*Uj8zcbwmRG+j2mZ;JfVFEGXn%96I zG2ytM(D;+R-k%rpDDV`9u6{URj_AzQXP0BcVNR!gd?ujjx zLHXI@#bD5~r|kPtu1}hNn`{(5z+@t^x^ZV{Wf)IUd+OY$wMEw>Asa$`aAds+6PO$4 zOB8RAw~U@5L<;M4xH(Ah&q&mI>Evn9rrgx9O&s zB`^oOWYA>KV79=>7@LSiF`<-J8uuKazHJ6{5KN!7zD4Du85T#O7LjaGIG*i(?Csdo zWjnpARTBa4@4^dA^qZMcr&_=N=oTs40iF7k$1kv~%)YY`h8fBz9J*;<`VH`7Ez4@0T$1sIn2zE4VNdD;Xo*N2MR> z6_{tWM^7J+{=B`O*@y;d>3mYivifcLbF$)Aa%-fLE4Aij8Wmu^Bh8k;IH%Xzqal_} z#(hLsB>pN-K$O}IuV#3D}t=jgYSC()Te-drN4s`hSgjRhGCP1HR_l- z7Ib3c%Z9#eg}#m+>lAOaZZd-TL8b(c_RY&RZ`&3Qjps;Ce-048#S=W-3Ie}pBswWV zfld5&nNgEvpXnaZ&^KBT{^s=-4gv+d>V{!OeiIFo zpgJL@KKf}~B~^_B?YBw-JxYJP5DDWq ztMn97cl=S8=;h^tJzai1^*(+{JGPUa4cR%G&i$lUvhWD}xeOP2RFRcHvOZu|G1S#R}R(ag)-j2~p0g){OD!}O{Hk1n zIsN3AXGbF|rLV9%?%5h<%~13yJNte)g%EjGa}qf_-63&W{Jp%G8ZWYj1;=rKdS<-D zg@U4v-o5+T3X?z=RTBK$H~Ggw#DN(Ip+QyEWOLhuq@6ZAp7e>hl9N@~TsjmRXe>}* z0U-=2*8W0-hrOQ(bUK3t1<@j0Q~S(GZ1CY<=b2_kdM*+{Dk#>6=Iv0wC~qDjXT&GA zeT#5jYqT$OPy;dA1g!F!8>>aKv>h8!ZlbcWnQ4Pg2CO1U6c`B(bEUzdmjzXQ_y4*| zYfvTCqr#hBg9rU;gXGwq{u(Hq;a7_bLw~|?`iV#Y`9UV2ilJs$aF~fN!M3dl)zt=s zL+mRKba;{MShF2_zEdiy*q8TvI+llzUH~Mt6I4zs&R}f@#3cU5A^x-J^>!#Q4mG#z zF!luPPJS1o92E|2m@vLnmyn5cPx}$-F6jnRAFb;T;qfJ;%1RYVfAZ1?LHbp>ffVWx zft$y5!NgOc;%7MWToCab5T~tKoE1mNX0rz-6g}Khi|7~F900tPuN!zK!ITn3w|rZw zS-Zx@&y);JBO}>PgiH2O`c^l~k1w6r;-M^^*s zy7mK{J;K@-D^waOv!I8R`$E9{-Rd!qFH<0X5Cp54a-8~t9Zb3}HX4#S@r3cfpXrGa zPyOT}9~QL8!WU~>H=7=d{#`R6X(B!k$Z^n-n+E2vxCQ0_PK+p6DdO@!>P;|tmq)5;T{-&vlNi&mV zmozr}Pmu;$@fWo9&z+w-rL+foh%Q*wm~ zU95mLtP5fZi;uGb?zm45I&%SuT_5#Ze=W&yjuW?u65-$l7|JZlRTwnIaGmq5 zKPnE^NzB!ho>J|5~rV{M(BllBu{bBO4j?g+!$A ze?BSiG3|(3lCCmWeG)sN5nx$njqq&~7(F?5ga0Q0^B*C{2~Xj#VK4L5nWu3LKO3X; zc}ED3-dFeO>FSJNN76BrOh#ek1Nm*uM2F6qlprNAZbmf zrPDCA67PY>l4mIFqZ$i`w2pw&Ha#ismNScdJltDVHlf&~KEwF`hwpv}jy;G-7POKF zyvw=QFFh(61>`Onk1l4%v!5vIQRo`1qmi9rs_u;8XFA=oUUZb$5xkDtho0Z9tt=;``71Q2&*ww8P`UDQmQ#(FlT2~<6o@!YV!2@-6y|3XYn{2$=_gy+NWF&ji5n-h}HKV zs8eWPVgV#r0@k4Bx$+P6&uXriKZ`gRS!7FCn^8#aiWfYvq4PPk~N zo&7K>;eG_2afx*kkVn4R34i}e-cu}h@a9tT<}%}c1U+W7`e{y>i*4P4N0`PzkbtE_ ziqqD1m)p#6Sex+gG`s1qSsGhj>uGMgw-F8je?oSGfUnFuReM1U?J}5siw(q3YbWsF z(Xyl>tH95n{rMAE1yt!j@$P>fi~MEof1UtQs&Ilo@BMjS1c(9vM;Lep!~_4?Twv_K zsQuv`UO&j|KXJo#P(O6@91?>nM^dNTW4%hBsgST#?{@UNwI1=Dzdr##|!Tk2Tn-Ry~YAJAQ(3iEH| z?7bfQ3EoR{B82O}yrYf0_J}-|dmp?}8OOGE*%Kcxb8^$8s2nOpqcE3yk|V&S0DUgD z5%fZs{CzKUC0_|puYKbnpZ4l>Vg4XvfKH&nU~01Z)k;QM4EOf#eK$-e?fJs{G1Z&a z;-3s{b6ysm!0>@&!Lug5gP?ggwJ{%Imc=|(I?Q&7+YF)(vs>bJkre{FNZ{ML+Q^C8 zy@hbVMh3VAtK}%bu2|gFbXDAc=UCPmS0++&zN+9pww;PdUi_KbEaNsQ0!Li-(H;%U zMva)$LXT}!>cnrBDvLt0%3p)jut z){C?G$WhGkFo7pT!y2TOoZdq{{<$(Ue zIv{kP=ZI}&gv5UkF3#s0bXz=>0wkimYVyN9h}F%72u!c0QQ`mSmdcvPnCK5Y#Tmh^ zg@D8th5!sQ?d;m?hnL?A#Fb*L$ z4?~Y6d~BnU0eZfW=Z8YWvvyvax%n6w#v?kZhkaKJ@q)E9zxF|w1w;C`9$)H*;5=xq zgZT^iLE<7M0ob`;`EBh#p)7~>j|PPA@G*F2w^ID+tk>)JM^dm z8lWTREpXdiAPCZ4ESW20e4c{DCb~XHUAv7=$9IT;BtR z%z8u~+1j2sJOl(h*T!prOv^aWKf$nnZGjGieKO7*YSB2CL6|6pOZ_9}Uu_$uCJ>+pA zb-CQw5j>jiQj2`rVcP)b;(5p$Soh3?2T>C;wwB|I2qv z@P&|>l8wY?`g4umA%S8LH+yl4UFUcJfEPuLrvnSfR1tJ<|^BR%9JwrQ0FbSudieO`CX`2^VUj257-+^YDol% zhd^aMtDo97V@7AL;kAFu9)K4UOKa)_VirU8p3I}}dX4Js;Z>(nwKVZEUzw@=MPZNL z!&7&vG!O$>B@hEBPv!QOxpKT4Mm+^H?Jpa{UJT_(fM^s0vVxES?^bF@hhA|c z;?}S%NgMSe8dpvhUmneSo$_nK9tlTPBKg25lW7RUZS*T&5a?*i!aKk0)dyU_yCnKG z*76c@wM;kKgXo;@ut4I3KZi%XXJ|ND^6-avp2m+1eo`S^tcVq~c$QfYw|~SpIDrd4 z+Z0It1ID{zs}I02mPSUH

0b4k*%t2i5m}&tBiPESu ze;F)sj>!f=RJ%`PdA8}L#q-g@p@;X^DMhQ@8btvLp!036B&n>QjOy=pc^copaZE!7 z7)QM4hUrO(5z5o;9h>}E6zG1PW{nLqsCP(rWl+jN`@7%Ltxr5*WG~_Sn`2ylCp3oF zJf=%j_(m<}kE|{ufpQRtR9Q>PQ3nd*P?u|j6s!yhL&3pAiQv}BO5FE&w~*Uh-aU^A zTB&8or_SAcvA;wOkwso?*X_ESkid|#(jhF~V+lnyS2ef!mOOkRbFNb#wS6zo_y%R? zR`}rfpujUaxNebNEl4rYjC|YOzx53QoQR{?^%{l*4ZSufp_f#PAPF{DO1HKJ9G_2q zj+s#`vE(kbcyfS`HP?T)Pp=sZpRc~`P}GG(!&hHSLh^F;T4`>-#+p;#*97~kuZbxW z$kNx-E8e>Rrorv@7PPen->5%WV#Pan zT0wuAulwoQMb_;p^x%O7;`YlL8}JYog>ZwXvuJ!Ksl->trXtSqaTFi8LxcFqoLuId@~4`1MaQ21a+ zm`v*d8g!S%-GYo$aZAmKuW_Vg+URBTgSKZV>4kV6LY~0O=B@>Pp{rtU#mZX!zyTo53zk8?SsRB==J@bO$PUn_mu)nL^#RQnBsZV3{oNKWS$ zDy6qo@)`R}X8W==TF^Y=@kIl*`~BnWlItZGKqQ~+W>x#+>qSpzteG{AmDC%(R8M9F z%$)XP66mxTC>>0;#Bru`*6EPG1d7Mj@rMvon>aw%b#0t5iC&W}x1ym$qI^ul-`WHa z4xCYdGoU@IDm4Gae3{d*(|y;?bw6bPG59?m$X{yR`r;kMt`iaq22I?bO1PEDO>2~? z1}^Kr#@nNe%y{*1?az)nT9A+d>d_DZdLEoKRa7R6cvTDIYvnjYG=L?riIMug^ zM9guYc@psy9GJ{?;1KcTi$rI{JCv^B%Pn3g5Rr@>p<^OLm`K8XPr;{ro_;943y2ZN zd({wZUu3<{J2VVWq4W&>_SY8<}Eel&v?b6o_UR9MXRrV zP-fLGNiW5-5fY`U5}95WH&b_?=457CyS7s|ErG1OPkuIOsG*VfL{cvot zX>v)r!Wb*pMpwZ|zprO{ZWUJD%@&d?DnZer-)A0P9&)cn)cbwC)TyeB# zTC?N+_2ZzAP=?@_R%s{R?$J3*(;0ea49Z_G1afoXEwb|nrojH z3x&=A(|pnwCS?%L=7VSD{b!*cNpmMffu(x+%#n~&6?n+9x0+RLefsQ=&166ilS*wT z${b~MlKm<>JZ0XGZH@Lf93J4MMbqAW5kgsu#74-NnCk+W@ZemKul$7w)$f`boA#@y zSpL4|)6#21-Gnn(M}U+-qGJe>3);0(K? zv#>zWVyW?6@y8)i>8t*Ldjes`tJFCX`his40vX7Cexa=Vw|nO!*KC3&h5ITt5h&>o zKg1@#3jg|PQm9&Mzn?Ral`+BrF#o5fkxyv9*k8YmR}vvN60M&w?#_iz+^*h{w}ihV zR2cbK-CEQ_op+Qup4Pc>u=GvfqdO?d|K{|X@Zx;q-NkW8@nN?}|CNFby-L;R`InyD zPj_V(car4W?ilN`AkZ16#T)B;31i$nS_SV6=I^s_G*uR^rk%$Z9X8)`J6IG{_X|(% z`cut-l_u_%{48C>?#jD;Sv-FzJ##vHqMEI=t>~~LcIu&*o9}*q1zkIKbArwboO+AR zv~HKH0lf^-XDwq+z!{ZZPN^>Cd3H_mH$;}Z1n#;unIL=TKxDhxgv!kY7s`bH97g4) zBM7eep20g7{&+>y1S`yk!wUsR9SovD8N7W1Rf}Y4sjzr%lXwG^^nvC+WVm*l0jnHK z*^z7u3&vy~1Utp*Bl>y|YwFcmf8X7&HvWgWS5gc-TG4oLJ-|@l+pF|*^g9v}AAcHk z%#21>G;xA%N%0(vg7Ke(J{JGvZP<>DFN4I2L_kMESjn5efOmJuKCuu%D zszLY4)EzfolgHUth$zbV{hDI{Z=~7dR6HP6FGK-HCTwpT_TEZsiFtgGQ#j6FOiJF; z!jnFk8*x7>kc(feH%%*#So3s}-()$6ap?Kx$WCnQgXqXK35SVeMxRE-hD+1$?8iF? z+?P*V*oqt)9QWGka8=~e4wYTiWy&O3*Kl7vw@TkkZ+TfQmVm{#J{FG18GL9Loah~~ z{H|8#7AsI}T(UWYKFlk{5RH$5LanO4KRcdPEbfqGj*?^9JF}}6wZYH5v@3E%cFD9^ zD$P|U->v1yG+0y*)T&@Bdd_`#&`AqhPtwl=q0y zHXPa~V$MKT$a}g8cI#;CeXWuFc3xWGh?K)WV)3+4cg3)Y)+}oH;W(A}wd8)bQhn>A zxi0cyp6#wRPnrZzT{oB#%=km;!E?ub#Kk5$yBOIa8O4=TauvfbURFi7=tSA5Vb^Yn z%lDRohulTNEVk{dB?kjnO4b4I)OnYm$gRd}Y=Q2zdkrHON8qFR-Aw_~M8wI}!$(>Kbz6;{wg@bI6dx}J-*rE;|AW|B3 z%{b#fwZvFNzrQonR0M+gj>Ycw2s;o0+cl_}LpQ+qfnxYnYnUeloHbqBH zX#%-$?h~oY{p`8sF<5D2w*T_W(igRb_LU|%1$PJKVv0AlB7hpNaIquuAJ{sX3Ajkm zy857zVY-&tujZvff6O z&dMa;$S1=l=PiNQ-JYbm0j&g#d=Wx8G+=k2gZe z)Fa02L?;qRHDsXr%}@T$`pA=$@J(5;H{YGgSuFGEb-HUfP-1PX=<%6L^WeVDlLx1s zK)tY#rMZl@ru|-Z-6lGn_Rl2i-(U@Vbj)!ln13koy9y{rM{}^TC#mq|M7;mpG|Z7x zp7U5TE29_$0X6|ak7G`pP1{YQpEMnHvX`z0ENO-$OiylKBqK(_fcp3ux0-v<0ipb# za{N7SHs+`e33<;(`n{ujKsi3{jF)giGX5+TxJ-_F9|AB{)?7gz~+OucP zd_Oa;In^rJdyz2$z&n3#S8gVqg!@GJ@x*Aj=PbS=i`mkS!>i#kiP6YuZ+5+G`(C4EhcBO`MagA0cB|g zeBUA796N$VEs2HIB1x$Gz7UrKaew%Z)Cj52NMen4#6lxbk75Q8${rmV0z&kn;big^ z<(vUJZ3Qa3o#om+E6pE_>7;gzc1^7UX}f9*RjTe(7uLh*|OT7>{YNWg^0}J~s{( zD6uz8*esskOSA0h=cQd6b9X~7jMZq=!zSJSdi~`;-gz~=pow_<*75PQAy?Ub>_3BY zF>2=XF}#nft{M|;L)HVf)3jn70VzHq?SkfwGR=+%QyoQ;z;z?}8j^@zh5Bv7$lR!a zUi=aFj^LMkX9GJ7c*taFPi`^I9i5Q>MUL6HrMCzqV6=hDRmeXQ2uuBBCa|-t{;XG}#gvkDOg7Ksqy=TD-V&h3ceZ}=tP;eN z%&7IR+q_7U1yq*Bamj^%^10TuLdYz0->jKbiBHTFEFD+23oV{`DY>UG(OsRX952z%Citz5#`c_lz-=E*E zoZ)^PIQzER;q-*wG-$n#h0?1(&IjvKN@pnowGFO+sFEvPgmtP zXa5oayU&M2d)eMc>5#g9T3u4=MHf>$PM{l(k@Q?utt;kaUwA6LA~M7^*n;+LamQ4> z=>$WuZ$WT8*VY0UnSJrd`5w8d@~-7Ucq=8(0pXr_sIX{`LU6-hN&w+mW$s-t&&XyJ zqIlc!)0Eq$|17pkj?%P`^6;ya@Q};H5gXvLxA^b9$R7F_pgl&ZM>`Yz!bK?)+*QjL z3f6FYB;%Z_^viZA&&$E4X96&%o7*@qn2)r)aMPOj-NHXQ5S2TCl|mhP=ASGj5pGH6 zbxLd+>J3+r!I0MmDe$zbq{v+d^84BLC_f`yf~S6t1zeYX@oy^DEeVGPziM@r(t)b#H|Sj1d#XDULPaNgxl zdni7q!6bRN?_5FwyLZ_&V%}WJOTI%l97%qTpY0@SM6KhMEWAGutcPQ1JQTB-2xB7|t%B6+4g3|*lw z7WT7-uy!=&Nh405cy)(Zb9~Juykj8d<@a*A15XGQy;JxfH`$C7tU*`U2_AZYB}0*-YVrj4ha_LqfJb9b0QE*|BIc##fAn+Fi2VoOQK>^vzy z$EyauY7jd`Ocw!si^!c*24{yYmsr|)RbHp zzqP2c9Sh0A^X2WnWY-)Vl8`mJbY`~oVA_+R5li=MW==>81SHzzn<6RMm(3>2W&ls- zHD|aYBA5!XndcqKHX|AHg%JIu`7@u6^O{aWq#L6mpVG89{bDFhglC%s1$bwMbtRV8 zDF;{KO|Yk*V8dY^@7? zbaG!km@HhwG<;#>_ifWius5^1o{-Sp2h04e%+K^z_8dR$E1$4>LJ-!x5- z_k~nKp(P1e&Q*387;Pt!4eeOY3Y5ZqbFWvVb;qls0I;I6)8f0&#*I*kQ!Qp?_P+0K z#X~bS8D!}+0v0(U-jEYam|B)`&Whz%Xf=fgty+6LauBOV=9WHh z>L)bxr_gA)Xztv3YzpQI3Y)F@mVI%YH#)!MIm`Up!&!!_6*!`>7n9Xj#?j*wEa}*a zMY5iKf>O8DW+4=V)1kTUvdCHUj?E-xvvP&!2p20Vtn5;_KxFT=^ND3V(P&zF$`~cy z=8G&DQcZ+}$8Z@0mMB(&kW?2fu-rS~9*-uMJIYcBZrr}{FoD7+^>_oxnDR)<$RNFYPYRDM>$=h z8!ED$d8<=lc0E2^xSbUsm%mNWdtdlLxDhY}K_szmMelVdox?g`*R1L0>xl#JDUjG+ za2!$knLUGw9!GwSYRi|h% z<&TV!yHQ@b5luYZfv6c-=H$w>KAr2QJyLm|XAKfY0M_z3VS1=biIjQp@$Bxc1rTfK z+kNa_oUuq#H0lPx7Vc7yU!2Sv$5cx>AtlmO@C#>n$Jec4riE7XU8hzFDhPvlLg0oA zvEZ^-kfUDI7VVO~tVkNVm-PiBFn2m_xM^oVc64m}=|MYNjiKml@Z~;j@9od$+U#!I@hiq!)gID()CVgZl0z&AY0(b>Pt|A?c zQEWpZ^fk6_@6uGn-0LH#N#TT_q6u?8Q6!^P{JB!&4}Um-w=uq2MhyTHAupOloul_3 zHb1$;Ee@uI{GJ|?<`%q*nlq}|@r9H)P$-YgmZ)strBGO|cdfCQuRS7T_*`vM!0rm- zCNB5FQ$lUYweyRqd<9>qztdv)zQbN#KLBj9`cTFCr(|A@c}!kS`?eMD+PQj;rc6%z zngQ01-2jD?o@aeA0x%p_XBXr5D(qooms)$bg~0lA!kZFE>9Sc@P675vrtMqzs;&6G zpFPsDM(;~LB{Dgm2|>dhH}09dSY32i|KNxG0L^=9w#0h|QTsoy*HE{m} z?U)2ZRjX@`(s*AhK*r|tGYoT>>P6PY#(vHKX7FVI6or zt+xf@RpLTHLZr?CzaQM*{Ahf9cAB+rqgPbhSaA1Dn0N?3Te@!6{sdA$4?6Ow{-PQX z(%}|z1f-a&B=5B;pp~GlF>={Qv;yk&Ne7V04ri38Oyi8BTKdheV3_9M0h>#L#ZC5s z_3awP_a}7^T@edY!sy~iK=$wr)#0?168-}m6H%PD&8%nBuWS^B0$uxyf)XW!H}{|X zreDuz@o!F#Nxo2!@kwnS8n_ldQDs1)Nr`7%_oKv5X;D|64RuhfMnITx;gt{3FeEys z)H7YU)X(ze4&i=-12ZnzuaSyVdlXK3)v>3~9}c~WZ1@C?67hvN;X&uUb}%2FFjS!t zIWjtT?=-6^U^3Leyi00H%xi*DP#P^NA)R*u0axtxyOSYMTf-;zPW_EbUwhbLYmM0i zsTL^>MmVC0{&tlZPzH`y0qC?y>S&qNZDtzp4^zAKIeG4c_bHt0Mu$Ub&|s;BzmpNd zmU0G(8Dc})lu*iNfY<}?h~S1W&1eYfHsapdbv>xK$M^SBn_!*6kn1bym&A zbj#o47aBZ^9On0!sa$P-gi8JSEYgI(DD$DU*yHA7n8rGd!Om?KV2sI(ehG&IQtNaw z>!$Rd5xp9(er$Ay+fh)I9TrOVG0crQRW$xe~+%@Uz93ccixKr$$;zBq#oL8{M>t)q}kgbppTSzjW{ zu=p`Zv=}=#ap^CD#&E>gLrjmh6IR-Oinff@)dZrI5~mM*Pw~2#;G~oo_C5z6$bd~Z zP+!Ae)EO=1lUNs34;FUYAcz5k_#5j2EkYKf;ta9bJWtZ?yoKoSv+Ta3OOXnkgtEYjt=`pS|{bR7lqQ>Q>M&lvRY<}xRE6QnRIW5OoQ zrLd~huR{lop!WIqGCl^zv%-KgD@jwkd#oXD{MS+HH_9VbGR zeDM?)TQ`Vs72qvO=6-jF`1n@IBrsa0b5tDP{GOpcowvTDL}2veNMAvAuPF=wQY8N* zdU31^tbUpa)`Tozw?8ThN4_$_W~GFKb$-7hdBwKP_k12*4pqO5|qB#GiE!ah*1D-1J**1aXJh zhkBscPIG|Fau$Kmx}VZjS+L*V@%~4M;Z6&8$A|EA6PXjee5cdaGLL268Z~8n@)96D z*r1@0J3eHt!NkaL4`YQqYLFRh9=T6-$B8ho5kGE?{>RskvXt{uG!{fZ{r(DNdX96^ z%JzFv-p_-(3&==k=6C;S8NP=A>vvPW;Y8PiLy>f?hTQH`c7}kP4XA#$*@lhJk{A)M z-n?EVUxJkPnES$-ymQ^hso@9<#H(3}QHgJ5!nGpFfUlK07~(L6lmK>A7eR48Y^2D2 zkiQ({FVhlD+@jD*0v8wh%Zh~4%;8~mnTCpB9^F)6L5V_$e@hK6=mJ>J{|d1HHwcX@ zf^Thmvlvexk{I;)cybR`g#8?X7Q(l~w$3Ho$J0raNDBoHj6fqXHrJ!Db0t^17R+Tt zU*150Ci({LKFQULN+n9ZF`)v-$N?D#{2lC5Z!E!gmU@v!h^EDd1T|6JxYHEZy)z#q zk>#<~SkPHROYMEC613|8dk}W#DVU>$Mm88SJ17Jfr}`wu>C&PC_yd?Q0eToi4P5{u zB-+&fryNK!gbn*C;m6=f3=jd^I+C1lAL`$Y9_FTi0-cI0en3eU7_H6Gfu0pbq4U~zK$t$&hs&9(>h3c6Q{r4uwmG@B zgJ4KnV{}mm9}^eMAdS`1ARQ`w=kQnIHj&@|O9g6Y&<4ilRnVh18K+=C0Ev}!5}sN% zLN_hy-=OdY&EiW-{nEJ}cpF<^y))?5Ra2dE@(#!`4yACHTas=6P`iLHPn-FeVYKM?oD2LSLEAyaWvocOxlcqtjK+neBLP7^ zVFg$komy!A79I!&!_f7`iPG8Xtc8;$rWly19v}@H4bQ>>ncok7SDREH0S-)>X}asc zn?RjlWVaUrj32I(nsNKPd0iz)blqq7SvX##99juta5fnA2#rfzlv3q+N(>tVAsCFe zYkR2Ue~N}AFKQP+JnAWKM{k7xFTv_xPp0!d-gv;LDc zfuOmJE5h>N{=jAoWA5^jk88oeqC`fQ5>**qo*8p<0Q@ldka;x~H-7Lo{=tUZaFXOFI55yN6A{^rN!#q<*Vk;|73M8{RPT?X>mrHCB&n zuAJ$g<07wh`KUcAf*fYQp zPL4j`4R2UsRAp=%}-=!lmfp zCppbSY|S?OrzwD9GAejM>?Axq*q!$g%qA%20 zu07}|SPquMDbipAkRt8i$zZ0nAuv=_8UQ*zd)t>SHhNygQCR*P`>1Zd-l+x9kLz~^ zGyTsNu6pTQX6?tRoVNiG`<;Bk|3d!BMTYkz6$ z%^h$xRad3=zUddsdE5KTes<+wm*yD*1MWGtt&|SK!gHw-;GEHVwG7!Tbm)8F!M8fS zYI*llD+S2BSnJu`!5~#Y5alnB0sOd|n!BPd|H3T(pWwwO?!WK*7sc^!^x_}$3Vik- zNBeu>|0N**#}WTQi+qy$*Gc|`fcz(U@~`{kpFGK5BISP(Cja+P|1sSE!A<~(ML8Ja z-_4%-IK}*V@Y3Z|0!bKUYUi>zu?rhAX^_sq5i8m;7iisrQW14Y(vrOScdaTAq%?`O|a zx=ver2TE4^6K>n7oPw@*lk0EXTtL>_aVY2oV@FjOFG0EGQ_*oasC$n$pT%+Sy=2e7znnkf{xkJ)wSRG#p25`TX5NNbP) zw74?h_3vx{uiOBu-cnHYh{}xiM*&h&2Q+8^`Dw+6SFUz)8L}Fl?{Y$TxVb4%;+AfE z*Z*zJc6>c{$zMNuw0eJhIB-!SAFyqI{|Y+$4{Q8yQ_ulmM!t&_cuR1Imtx77_a=vO^2y+S+l3T^IYC zhAFR7hM}Q`$LT54BBz#x6@a?8uCxLCYMHKT{>STAGOjO(0w0{se49Tkyv^RNUNHm$ zDYh6fr%q`3w8?-H{AiJqNH*~9YxU7iC}NZYgK@I|F3WU z$fH=>+U!_HLn>F2cHCv(N5~9E=^``g;#Ja`*!GOpE1RRoJ!S;=sEkzC1I0u#cQ4zo z`}2;=eJX0&A*pSk>b1Piq==23UCx(LRVwOVg9upBJ%q|r!nLDFv?It}k?ANzAmjFa z4ov;}S95z+Og1Z8Fv7knGk6V+t{`-sQx;lyMt8dCtqlT^!n-s`Mo%XDWJWY*gz6ND z#>S<+PUi95Pik{E<}dZ~n%dW*3w2euPYTKRMZ_(dFEeB#+h4mmB#m^#)F246Sqo-s(7!1@QvU z(J)*&?<^7$+ach20WK_d#03bS5x*}q94Pw%?7Znx=fW!1q=z)u`cBb_(&$Ufm{Y=f zu+`U4>i=4d|1k=@HgHX==?PG<<|al+CDqHVi^c$Y(v3D6$4cZWzuzytVfG{M2lJc(8xx@f@;qKY*V8;7oKS+&!ra z6B$^f-feC4Bq-k+5#7o$Upjx)7)dmE3VQl9UU|)#s#>`CN!t9jrb+BtzRG= zT~zc`x08Fh6$KKfRpMf;)@UnOZ^W-r;Z3t>Ha%vtK8JkpVEAXzYMf2Hn%7o|>@?3* z=fXUHHvu~bA6G8d^~;_!m%iuE-p;D_Yxq3%mr*=L22c_wwusPPfh_CJE`ztz=+CWl*5P1G&Ktw+A6{_|fO+-SHx$cE!usJR|J` zn5*?~pu73fZM3_Vkut*3j?k=4Q6&0pCdEU|QOuP!=ayO*NORV-@y$oUx95;e!~!7r zGwc3>*0;LEvw1y>=cDEqJM+on>~&zU1M9Ga_XS_bRaMe-Zdq!-kiAK`n_h$W|>I=~{kuOmukq40v8x|vn z{a)I-+lzOSM3T8n)M2)nVHS)%MmtxtKs-WHEf|w1iD-KD!+pAt_vEv1sYp*X4*ewo z5YhZu(nKFqu^j!oya3Vhqm0B^7|}TM;|9D>Jxsjspe)eVE9S|5ND5INQFUE4nyA!s$#uzaNl?2D{U7(CO*ddQ zF!D1N9A7cCFrFM&?h>7^mLUaagFPAj7~yKLs}8;pcWk}LF~n6)e}eumK6&&@(_>AFy2q(qWLx#;czu?HVD#P@+VU^XmdKphx4KH(4#ZDbPAK1ZN^kQ`){v1 zS09qu_-*C#OhY&9E*D|??QYAVKnYCsK~XDWSjhw^W^A0w8;g7WiNX@Pjo*hfphG=k z3&DtZnhWj0M1YLjOd&03PU1ccHdm3{tqMYRVgnfsXW>mUy72M;Fbn_k)hBVFTp5jL z2`;R)wWdK-l7y0E>B=d;uPX&hqe_L&QZ~8HS$%GC=tOFwf1|L5QOr z?6eidmWmb7Xy}{?eU1CtrYVTZ8(V`TO!P_Q#fO`-K2U%NJJ*P<)fAxqI~>NsHbh`} z22omsybgj~kbpo?WjvdHn;#H->C5{_MvQun?Lu}vAR)~qE`GUDe$x={D*|O>UuqFp zbe5p@jKCD@NrN~^$JL5WwxgW_bpVpnzOw1na4(`sKQ(VCWY^^4)N2VB4r~4q%`X1! zDF!mmi#(CG18Rsa0FfwMgQ`VUFzDDTrM&9i7L?`(^oR>DZ{U{$uzSo=hEO1k<{*NG zkHVMc6bHg*)p1m?^-t0&cz>u;7I#`E7$()sL#*{jz}mWcRjNs5Se85$V|(7Wi1=ej zuCWS+!bY0N@7=TTgY@}au}#8a^j(K?IUMmw!5i>_^a2{gVmX^$u9s_x3y`#D`<42e z&ai^Tfwpt`ed^OCeS;SN6z_}AAEPqWT^IE~GV6<9`uuF(U2Gk!wcgMfhrf71qn!4O zUhQ?)gA0rKcp)Idlp|pJG%(9kdWa=uD3lJb*uz!Txh}SfK0FoSN45O*+2`RCNS=ce z8nj25Ol@|Tpn}`t-ud29YWmVlkq1zy@k$U7l1ipwIxw^Oi0<&+(2tVACk?bDhXl8* zytP2|k*bWLN8WfF0 zSKGsc*uHTNSOl(wr*Q=L=Nh76AoN`n(HWc8eq3+FEBmX_iGzf#;5g6gM2_)&b&4|g z8=_XC;#_b8>5uqu6NMNt$2Q3;M1^OG+C6}Cae5%0f#6tdo!MN~ zkOsoZcF?INCiJXs3Y5#n-cICdXW9x@FezenMXUjs4E`e|0f-U$sfFh-QOtZRUw18v z%KDIRxwQms-5T>Ez?@9` zLIUd@m<6mE`xU$c;p%f%PMa}ZF{ojHb%^0GNC%7E8(yW$u<~}dJy6_~5he^UI7K1* z2suA0TqlwPs`y%2kKhN;?AzY!s`0-IV7PvJ3mPyOOXRrlM)qyApIoGBa;mdod}z#g4Lzee0l?$FY7 z{JClPak`+q2#d9mE8ydmHP%PmMlkYacsHe~ z2uqnIcan&YEZ|`HUtmJ}wzggq4G|s25_gAJcoXm}ZcC)v5@4&KVf!RY$WmXt^U*{j zWuz^2Y~9JqDG&uee_cpegEcbv+6s;HD-ft$hf(B$2M(Wpv~C6WC1{TzK9*a3B~YHSS!2nD7HGdmsdm_%X9uu(QAL4ug->54DX>Fx$;E2<^iKyjK}8 zSNbzCH@trF^e1WAUVa0Zocf~0*3NCSZ=Z#}L_eUu&s0dm4uB3DR!kf8wUv8rcC6OK z=N-^YOe>M_hB-^GHX6q_m$O^cKzB)co*TSjqYOdIy(1Tv_owcx!j<{aixS)`bn@w0 zR`gVR--Y|-cVzRQ2EV*HwVL3ApWQ5b9}LDh1L|+t1#`l*bSbM!Lg>lvlZ=9N4Bhyn zvDCAjQ`#trFFAc+xTp`Y0*Qlo_7{j%P{}9g_0p*EyW6xJo-Dn-5 zK$WW^1BzG#n5}1D9ohl;{Lwg&Z61wuatnHdIW zkUup7%UX}`Pdwqv-@)so3TmK#J{qJd#$eVT6+BDIK%xaOn{PA9_P50l{Gob(Of-FkA0RwF zaL6}6Kfxfn*l)+~ig15@k{DPi_#V{pbR4PY4`Bw_X-+rsI3Nx2lcvSb^kE5dtuEcO z?vw1rcmo$m42jcv9Z<2TWGr99WZQxj`MO1dh)Nu&_~a^x$@vUzS)2|C-OdI(9ncVK% z3vQ3v{X@O53C^{G^s6JBibp_On>9>%5licX97pHwKfnPIa;>*3MK9fM-=RrxiJpyJ=lUWO?em9dEL+uQR9{c?rC);|tO8X!)&RpIa>YFs0j6uyr1PWV*+pR1t^0Fz3--~r^U+IwlMxCK zmZryeVqRrW@4+pOE$IqW1q{2?LFvYyLoCH%nq%Pm^s1l@H1c%?vXb{H#fv$F7{F2{ zx^bs-+=spnv(Dw|sLwLP12N}58*XppBHye66jtbnh9NBGu=xQHH3*ybjQIX6HC#Le z38UPV6HZe)q9b#(#cQEo4)fq9M8!3V-5v0Dou`7&J6+Kdg2fM%8f^HjH7i#$@CiHt zDzS^$3aJ1hyaK@eIF0=YvX8xp`}y4yID#_ZXHf1~#@Uve#JXwM3|zQ~X1w3@6&U?q zIxSI$rx*tNL5pCBP2U>_Pzz9IuBS@^ywAoEwENnZ605G{*#xNqjN#)DzbpApntOeM6lbFy+zt%f>&$HyjP!R7uBmnu>lw6K@*c&kf1p8jh=^e~ z4uvFlI#@D&3-gTtd??>1L!$bSAli_q7OS+rpFpy}24!5l|B!~q{e_@7pYO ztOF9}5^RO?bn-A9154*G!i6uWWH-)-?x2^OKd)Hf-(Ij}H90P8OleN|Ty3E5Oj5{) zy_|n(bRt6Pq25=d>3G%07()h0n`VKp7Zs0{dfUwM=gH1o zhiB7Y1VRYS2J!$lh`wA~)xPWA^!sJ6r(2tpSU!X2(N&M5vTN;kd3o~i`os2=H&~dy zQv_^bDY9jcdP&^VstG6~?8==)U)2GJdU#sNUodD|)C_v8DW=c1%L9YeaeYVAxi_WA zowa4THpEM+!>pys$m>I_6t!m(ZhPcJ|B=;Ds$ON+aS9P?F_4sgwfBX&wnMIVU5{ic z&O_4bbq@`on0rb8kwagmTbZr^80FO$wvWC0X_K_Jtjxdo4Hgt+vfS=f*f9310?i44 z66jfzbfUP);}4AQBjooN6<=_is3~yw^%4yvi75y}9}HDfrD%qiw#>#=+)i@f#4`V_ z>JOfdQ=<5WO@du&Zna9kW=HUT-<-HdfxJMZcjJS&Bo^L9bmaDUkuBJ=pX*7)(UHxK zBNR*DA2B}2#3{0#A$a>^6LDz=6SGg*&9*IK8tyzy47#EEBs-`M6|htgc9{DeSrg?? zt@{)n##>PNb?Vcj-4(hA1(l>RuNHogo}&nHYhqF?2FW}wR8;T=6I^_NU`IR(;eQ=B zXnJB`BnC~3Z1E#1-&P*v`PJ~%@1_9ONI#E8lp$cjB34sbZduqPK$raeSq#O*5z>z< za@|PNYac(E&sOhey_8P=<8Is*5oVf$KM%1Qz~Gz=PLYytxF65< z1Rx9P+lu`BosAhi2IM0&a!;d?qvv0=8mHS9%AAcY*0D31Jxt`*?L6bkW|uLMkq%bY zNU~!>{Rl_xjJaK6Ce_%ITs1AdGq@R*zCYcfxxPXQ>h!HEJ<8$L7d)+?6E&=Xr%Ul? zGLhZi!wCxAD+7naYVC073h=v>O6eJjWf|HeGm~)JqXR2;uQr5D@J%MopeBBCB`KjrP3oDabH1U?;&Sc%jAlq1 z-;ZY}5Bu{My;=rka)wJp%?sSKr_7^{9tyZs-3=4_g-iGF?61WlFY)?LfNy6ac??s_y7$AFnvSyr~3goA={Eb?YeQe3_QV!<9ZiM@no3L8?N6=;jtG_kXHcG|s-3k^z5b zT5<0Lf6jfFm(>o&g3nT46GsP}wxtt6Ff6uz5c>VZUQU+JU!)cVDP*{tm@V6#Wxo4y zc!&L=y2JY#6X zMA>;vZs}0(B05_|KE(($yI)9}b(v$xc!8?99*;fVYQtjSbIv}{vcz|_gLje*w2BZg zb)#8JUC^x9f#xEcVpJ476K`R^K;@mi*Hh-jXh!J z8fcB|$mjv079JU|aOB&RG;S|!q?wQEj897A>1|N4%g&Aq)czNA8yo-!`b5x!2_At6e{%vMc z)dm63q@m@APS!`*q;&tCO;pm$9hpum?fq`_61HV0C;A%cldh^D_(L|y9Gm#~%-4)0 zu67n}V0XIT5s58`5%4;-t>6nI`k^Jn;aq?3MW{3o^a^uB5;x=awn1LM)^XVmO^E8d zl0I&ui`|S|dCgS9+)z(FBpi$M^ZPO@bO^M=(ElM2X0Xo_e&u0o9}6b==!x1nwpHEl zC!>8~XhJ#Js5$lib^9j|R>FyQ?{<#yzN+>z5U8+NW+%&BsHNoyE@S#ar!^&x8YIqSXVkOBw zCC|cLUWc=T;(}GcZetU3TR{i$a8X(3&D8+gv*Zoa$4jHUL3IZJNYU};(nRS@?}yQZ zY*S#Yq7T^`10N^#R$G_$v5SsM0U=%R>>sv-WGg*W7_G81zjtxss0jJD^8WQ;PW#$F zBH*rhVTW22FE2Y-_p4@hv}H5rS(&mW*tSK9n*3d9Qt>HW_c4N9NB z!8a-MB>KJ)!S{O4*w9X!4f{jOzfkM^8Dd)gS37#fqZVnlF3X)9 z6?G5ZSQErj>Xy*sNzrOvj?0A0ooL&m#Ht85g1Eaqyd_e>k>-W6H&ip(LQ}XG-U|AYhwPHO8*jGd4UK0H4K%#SF^^>b?1K_oB&-n-isD2$$9cwMMNV8E?`J0F zxu4IG1qM2l+d9{ZkIBz}nA-fhgP7uCLPSarHGPDG@dM;$U%VlE&@S>8wu)8ST;KlC zlKG3n{deBk04ibiaIx!}SG>|zefa^|AOiVDri1xdaq!u0DWX8B66^Wjg!A1c0Mf4{ zp}LrGW)}7itae1=(gInzS6!>f2j2_PnP$9I49C{GlF*Pr!YY7gTpc4X@(CNE5bJ)o z2kVKAUm2s5m+_6=o1k$B-*dRCYvFYG8b4sXRTf!@2D4l7i@1^Enpj_$GE5>SdPrNVt?$TPiAuZtT8QcC z_E#D|fhuR$7Er+9^~H@{lvAMgsyiD2EPdCeYD(la|I_y*45jn=?D}ltu0x`I2mBW^ z%)Nqkl#%8|?TRS_KR6Dr=#UAGoka^@$(yGo%`lY{Su_R@^xH#Hc2*D_Z2;f1la;(N z)y1=u(3IEZ7zBhD@IBX4$_%c9_60xSQTj`jKH=`o31jt86F0(muv4`aR|S}frVnUE z676KXaXWK#5^=&MPaPG?iRUB8+g;W50~v| zFF3BL_;sCyMITrAbX-%?A_*66Yu@GeOIy=+@W)=>_aDzN%JG@r2Mt=s+Gplp^p#c1 zdIgQdC?hY9x2nnDs!t3so1T%mY$VC4=X${3ArA z@-Jp)m}fE^oP72Us0y{-l&tw!0V{2^>!%7=cX9CM9)KenN83`2t!k$2F`P?t^>9+~ z3&B+-48@=UdOs6n-M04zG|gzP`|I9?#f3hl5h2vYgQpG{UXjqWixzli=XjL#YhE|< z9q@QM-C(djc>>gcRvn6K0&!}j&G#ug5*XiJ}%>?>(&Sz^OePrBIK;J3+| zgGWO}xFn@8>-I+sw{Je`eg}G2+y$y5G7H+n3W`3cCe#Elfw|&itnY;aCjT8yktIOC zC$R7RG`p?oNIObdcMgIKZFuXDb5V~p7 zB+sDskDlwatE?ubZ(DoSP8iSM0S1%P9c|Y0LZdoHcX^6bUTtK5qF~4QTC5xb)5x@y z)cF}4>wL6utz_CgmH{oww$0@cFtrYZ_zKo@%~V@B8L1z7VKLMltrPS<<9`JIdBck4 zK|+30-%QYdwEJ;I!d4ri+AxP~&3ZyXl()6F&UW`X0lPywgKvkA!o^>_TnENtPQvQF@@j!WIzv+eQUN8*!x*i z%?bB-`zRThaKK^Az~r3yU9MUhsH^MD?oLsBbF=X%uUqfhNb~K-hF7*#>P6LetFjOb zqdi&xFO~7hi$vRgD6NH^{9xH)uk%`zIN$%U9ij8SVOjW3`!%PD>2HhYg5>IJW#I&Y z5Y2f=OsS9^iKyri$)i0lVzpXW%}ckTq7B?a0+=0+v`VuJ_n|6<;{2%vEiPqn`7di! z6x->eK*;F%w@MxRTrp9hv-{b*9++0d~GWIVqL|GW-@r8&L0Sb}c+R$d}SJ!=}Ck0SzNMfz+aDEtBeHoLxMEGGu;VEIdC0{X&`Gsr&gD8s zh~v#t&e=%utwN(X&28WJMMJuk$r((}>l2pm;~SryC*c+a(<%(D2h0SIMd_9@qvNku zNa==_I@dJZ*e3K{VEHj=1hL7W#WRx#_Y_=%tm(EZC(+f0xPd`M zi-h&c7SFS}r?#~|fXK-ZO8Sa1^KQFfQX=VCav;WTP|V$OrQj_Z?Yo6kA~%#(ZB zXbHp$L=P$5AN=+}WLy-qyrtQHvJne)@wCS;hRo$%A>+eS0pq*8z(D zfM4?#1UJ3{i&~h@dw|`H%-f#zs8ju+tzA2H64uUhgvEH>FLamone8aWmOs$G^u7su z%za)S+7r7bN{zhqbjiDd5N;LY@3rv=hVT{U#_7aV0j$d$n{N-&4U=ycq0< zZJ@%s({lB;#Q2r19@2NJ93d`U?VH|>u^2Eb2G~6Ue+ch?rY^jlJlych%2;19yfI)4g&T9pBuiPgcnU^{r>OWhIYdo-TkN+2 zo0~SLp<15qm~%scS%i;I??v2wv;WF}zklM|GUV-tCUV?zaJ5+(nK6;iLL4sD5{nKP z>LWvAT^j{uehk>}eBTAZK#5(7yKkb41y2oYPF_tt<+kN{kh<IRM8 z212NbxT^ealvUGm9&r)+o}Wc6tY`gUSa%;@lE~r4LSN#H&0!qHf-+;hdxMYRfRrnr z2mmH!eH_^IlB0zEA8qdOZXTcGf3)Op6O8cPC##T9u?m{`)fUrzNNTZca1C_2F4LW_JrKXv2(pP@JBRaD(TPNCHg$@)CvDu z{ncU-;@GZOZ2csOZWCiscw{%}gIRnS5jl|~mr8U$|2qGja~E$hjqZPc_~%+hfE@i^ z=D->&wtFWQ^^T$`Em}4YHsc8TpN6p)Sc*%mH~_gpnEvy+F9wZ-4~`TJz`?-k^H255 z7qg7Q9uKwiTj6@tUYz2iwbE*O{{OM|)=^PK-~YGdfW#n3!+>C*BHaw7l!AnyfHX*h zGz`tqN{K;8i*$Fx45@T?4Bar)(C}RJ`|01G&suk}Saa_^H%{EM_j$edJ~2i6ev*p$ z-H6NL{tfge2IYUY3x89}a0?s6pfLivBuPIg5`AOP*|&KjB2x~_n11yhXGC%a`v>03`5T6$2j-X7`MNdM z)vmyEZBmd}(apG5KVwAnZN5yATeWbCAAHgnk8^XKl1}J_t=@=A;ecdw(n@@9T08b& z)vOL@Db2g6cCPS~J)y+5Q^#r<-HH<^r1#F>1x7i;3L z@u4QBIWx=!V(}*i$=?u-%Az#?m4&3)8_E37+5o0m{7dd!q+p35D#w`(ea0!}yX55z z+>%S8g`z3X+Lbh!)WH54DDyP0AghpKL^_N{SS6CML06aW3W zf%YrgJxvv&FMg(7=COK*KlANS%>nAdW~ft7*BuQP7|_pGv0-wj={?_;Vc(Z8eiHGV z2$+8Pb@v}H6V$>)0#SjZv%wG9_qDOjp=U z0@*HIfhsS5zx#I7g#8sG#N+Ad2C0fd5a`E9J|=Np;C8m0$Zs+G%&dnfxOK_z`|;L* z9_ZT4|F;eJ?Rv*`1%&)#`z7`Vp#JYY|JS?#Gge^y-ItdFf2Pa8m*ZdO{<^*dP#j?G z{@LIlmOtCyYySpd>wi_s->d!WjDH;azh?kV`JdZAAH&=Q#^sH9alTw_wmYcANG!%; zX|mo|Kmyr1mQS3w2WnF}()E;3Z)@4N{L(ES0trhl$Gf^X-|5@kZI{kh*_x>2-7b{d zxE=ZB(lYT>A#!GH)uT>p4oRU5wFkn#V`ir<%dJMYJr=yswaY5)5sX(eK<#>_tW z%g%OPD|Kvq&Ld49j`pR2D^ENezj_?$UY%S`h@Yb*Cd+Nlrt?Q|z+&jiWww}g^eU^5 zZG^*Qh1FT)vU^6j*@kWRp`yg$klNKGgN^rcoS6f#vWJC6A)acgN~OU|>f@U{;c3wM#}_JZPFOF-4m$mF5(uh#Ro zEv957tqv&>1E+mk?UxfR*Xspt>q1fU&CbjG_B}#% zm+yVzJGUo}D4lz@-fNa{f*;u09(amg96Zq6So2hKb=MQc>~=?3Wx*o5CeaUPzVp1g z;0GNqUi2}H#%`Hh{o7docif$-KqIm&ztBY;W-AA5ps2t%D!ixaXW;CP0`+ix@exup z()!UXXCvTA^3s8bYI9R-a{`tozIO^Q$pK5P;6C>}A=||C73;ytzE5_E9xMmv@;Eo5 z%I=-#p@f-Vpte`HrfJOVr8-KAx7i5b}rmGk?=Vs#IvBQ)jRjnYVa}4XI^O# zka**p(T?a@pP0aLu^xsW=dWMFFs{nER=rjebN!h0hJGY&`~qF6{@DL(P6tG7CJUc; zv#lHZvF-$foqlgbeW)A-!E&F4(?)dssyu++dG||GV!%>dDiky%?0z-Ro5+9&y=9Emd$Dr8DM*2HKjOpZ>x-IA+efbUTJ4sn{>%IN%R zj3R!{dX4(z^dIbcB^A1SSuwAKm}HtCSQ*EqZSy%vtR79SAIKQ%l}zA|e3`*NP42{z zXpp0waYByb3-0%`p0WF^f0D>DcDgE>hGJTh?D;dO(Y&3*UcYa7?BAs4tI>i?wpXm4 zmJ&y|UMQL|TKa?7lSexT=;5Qt5@oIAi5sMauXWW}lg`}E=q|F(UakDzpLOvpsIhe; z;T!6^Xv1)YUuc&ZE0)XQL^7gdGIMscF@X&jXgje}Y-U3*3|s=3<7J*OM3f1T+DPte zGHl)6nek-QLNjvxmQB)GW>2GaNfNLxoZYJtTV{nwyLD}Z5! z{Q$)4^T-gG2|#)}=iwYb(h) z5aehQeIEVBfUA1pTVS!o6%)GTon$M$!-Vb&FEoK6F=aeSp`C|9vW->o|> zs1=nJDgJfiH8;t$uWel6?~;1=&817lyUxPj_p-62#2oO_pPY9&(KT6COHioXDN3D` z*f+c&R3~^C+a^GsRitDsn)=)Z?Hj~j=%0TDrN;)thzpP8aC|avd@VmG#B+)tQ=U+R zAK^`QUTg~LX>@FAA;k^joka@qCJR%;8syya$5*;SO>P0%qRdaw2y4j!$+S=rIMzz_ zp!^ViQV@u*%;JXSvtDAz`(-yt9EXpcEp#RWzGcgJl4;)&zRoFzIV2`M)n*qkNav`m zh{OieVspJ_@Rv@VSG35HNw7q&3tBUSmeV%2-sR)#UL5b0YFt+K&^9g-_lRxYM0x;F#^EggdFZe3S8^yhx{Jg=@nLWBp-#u;!@XeG;3Z$`63Q z(%D46@6)I=Z)T~oo6Wf3rmI-FRAtP{y0@_yEU(&n#tN4W8iSVB_t?pszKKE8Z8*AZ zxk1jpt^7}ti>WBIFFrGg+P*lQ4IiS+swVvbcI0Rf{T!C=QaR{GX9`>nC%Ucp1WMN; z!nt3DN9Rt5-B-07QbyX6Df4W)goGj0R4gyu{%c~;6OtEJK}FS`74Wt^40fMQ770W% zzAXiQV=}X|1Ru=zwWur9>xJEq!7(2ZCc5cOW9^J5L;Q>ZUY(u~G2p@|fxSZs^^cMt z)=tlIj`T~vGu^qFN`m|}o>D1b14sE@XlXaDoqakK)aUf_A|&Z@yTyh+<>@Bod^hoQ z1MnN%J{e~qi)>4wg~Vn)(X5G>1q?era}C#sO)CwU;|;lJ1sqlS!y0c92o{Os{x1;{ zExH9hOJ~upv~zZS&^{{^WnTV1UO>glA28d$YvAr@s#*szMWYc@pyfKkr+o4$n&Q1C zx&&hEnE`;&IAxu4qaIrmyhZZESXU*F_be&7JL$H%4L1dWws{^e(^HD*{5#ki*7&s6 zwIv2%SljQCKPpB1tr#fQjR$RS1fbdXhVR<5E=K?PXKq}9Wu%(F4*1+Zdr-Qa$) zlQaUWa|y}HF^)>Q%+h^9DLu(X6WxBeZxzy1fAathsm7BI;nbMP{gV1@g4ok)>u0Ls zLQ zIEO!va%$0i3{E|_d7l-55$!&L7z~4^`kOQYBZKAH#l@USt*kzv_iBuwOmBW*!~dq0 zw5j7*+%7WNvMzvHP#9X}eIXK&{2PhvqSgGucjK|q>79#!E1*fWrU!;}iG&SvKP%?> zO$dMqG(oc4!0#*AvvTI>4NZ!LfN#Z0XcCB@tt}SxSUY9+l7fqLJN2SSBvtT@^ug2T zeO1~3v4rR4dw}TIq+SYm{h_{CeCRjOs<0u)i?+z+pC8)lr>Wm_w_PL(;2`e>$1^|z zq8X8Mo3GpW1-6S9XY9f^act8#07VqptE$ZIrjJ#Znie`6<;BK%71hOaQYI$%UNm$e z8p@QzH>P@F8E32)`@XzqNNC{Xzm`_C*`z5o10zx_h;<)&I z>8-nz`Pv$Zdrg3VrbU1Q-z?9|ok0k(pg(B&A%iu}M$;NSKoBe4>D$IcZ(m{%ICRs| zpJYRW%H5=|0B?`mx^LiH_nXg++n}gJ(^<`eyU1)R_ldS{6qcA`mmb0L9{U^?@FlXc z$yU|V@ARgG^_`;NF1>=a8G=;M6!TvLp}r>W*e8ScsX`)irlxS2J>`ORsdEL_T+=9#e8n{UyVdbAQ`lV2pt{}iR4^td@H zOy;#LU-H`GZ?fhJvW;{QaWelEmO}_4R!cJaO9^TPbYxd`*Zj_XtG0jt;iCB`2 zue=-n%popvPxg;1GP((8I}KSFE>CB^9CE?{U(Tw7j4#;(lfAWUtck>g6^F(68PHTa zU#XO0ni8n1lyAnuR~x^n)Koe?Q>E`l`fkCU;1ivi6)QFeURVl=+BCkqM4yR%|m5c{Xx0(_z(r{xzK2~mp z{w7$Hdf5V>vP&P7kw*mKQi3Im`pS0| znstFhM~|T?NKI`wVpDmX{_k_Stx=YYcB=F#2OPkth~S?x5Yy7Hxf%tK@&q>#+>I0x zH*AvqkJ!;$??g6II)`@&09SXyQ$tdQ=QK#Ku9!h?p_+ohgWKd*0AO_cV7?Fe=&&3m z&L~+@jKYHBrepb%j{Q3O!2v^Dnh@hm+itc4eqYAfr%b(kVlM;9{6`ftcN>5p*uvx* zmUYmThsJU5Pe){D(@MpPg}243S`T@`!m-AZg}~J^Ya}1t>@I3Ivg%wYV;=R)pB~!g zLmaF3u$yjH80*g4y~dm#3x0B+0&5iNT9ZLhPNDMy*tfqe($9A0)6vqN*xN;35qBDS zJoI-k?h^gQE?*?_x)}mP>-ODM$5m``Zq{68y9$>*0R6g26TUU)1;7o`!YpiPXPuh~ zV=1v9AENJh#7@!Oy(6iu(zy7<$aR_ruQAI-;=jNQx$8q@FtkQm-3!)8E9=s7SMoGv zCHy*n93+mqPhpsIOVX!HAquVrBsci!3(`A9=7q0a&mXa#-f&6pL3UK#$?1M<1Zom< zt`Nz*!wohM;I*Y&Gkinr;D>Y7BsNBNBp%%={N@{@7_nSL{%dDo)f&YYg7|Uqh{=kJ z`R6eisaYZ7dzIkp>du8z1LLMM^kX|)l`j7dt8Z1W>eF_Y~KUQQ=wzIi74)))rr;5B{xy*#M^O;v@MNuQKE^Ybl(450R)JgT* z;pJRPjl2x~8VAVkJ-H%b3mt&1IudExt6bP@<-7-=@BSHqAU@0igUd(!iX?#)joT=1 zIv4k^F+L}{y`h32`5{@6qkhc=Zd07tHct2rz@Ru1VNT(PrTEi)H^$cd*v6u}mcJxt z9JjR~{?WM~-$^$K6o9iVph>sx9tfmc@pU#5*=XL2>!|};p~#J&NtXy{*<5$O*RnFs z_ja@huw2oVD}WZ#F{;j_!n zFEMbbUNPs#xl=;Qmv#6{ki=?xfsHTRYs*2%egj~n_&nDP5$=vmlNk%dT;WoLac%B>tM}1aHa9_&%}x-xU8t1;k3&sJ zwKBW$t)b|~>Mgzr=fv@&uX^|QfRD|RLkD)GnNO+i=3{J9tI<%C;wR8#lVY#aQ=V`) zE>1{VCJ>pc?~&ZA_iWgM6|5ZXJHgaD-(~p*UE7oc6`YjWBiF1vll&H^LhwO~dFRVF z9U4NOI?aiD+84;bROZUmKdT^rXyV;5DMkC0+n-EzHNr8b(b@pf;_#08-W|SXE>d31 z>Vk^SYD}mYgCz zd9DVHA?zocaF9NzA^3LM6vGvF)omdpHapGEbF3XCkeE-0g)z({FJ@1iZOgR_CWJ)T1#LlFJ-<%*IDZaj#a(aWH0Q(1?ODBH86Z~Z zETb7mk|pqh5`L%$m~5-f?^~THu27pHdEHE2$7{JPsz{rV2bH)K^u;XnuECGL{qF4(6BpqXGcj`8EzfPU8h+z1 zX&6P`NSF9bDz0uGx<+BPRJ|pX=^#T_+9Y2SkWBkP>sSMM4gtnNf4fU3&E?!US*$%wgtWq*d0b^SjjbOOjH&J$@G)g(`vya85!;l8( zm{(b_5036y86X>#EjMw4#^9$4GcR=iIOpX`b!(YSXgiJD@89B5t}bFvPIgPu+d??- z=@+sXjw?;S$*@X`Gl`qtJv6KD@T*p=ANpC%KHWGn(I);*EcSi=#qvX%JPH$qWC3Xr zRI15radMYemwW7F`q|4_ikiYaUCz!8E4RY$`z0>3Gr!R(Wp%idKQaw0s#r&4=w!Ew znZLkwBJ!H^Kv?G~sOetEEsrmz3zHkOvGWX` zq4R}<#oX@`RNr&5hi?0)#c>?3Kh^Tr&^Cy_7_2a`U|ZR5ByAjeGR*qzpe}{TQF6jX zDEKhwu^d|(KJtNuaavvl;uePS(hJ3~?Q4ToZ_k68rkerj)6PcX(s&vD^8SQIm zN4gDnMn=f*`lQMFwsgwUa$h!wd!z`=n zvI^4|J+kCW2*>P+Ytx@a6x(_McWK8wNE!Mp0YyGe9lww{gcc{@5DxL8< zl_M%*jPB~8-wRR!Sb5;5fo4tWGjRZ2_lvjpVd~OJH3-Bf!ljL;5O4Y%k|R(ULR*j` z15ErS30CO@`l^E6jcw->fag9>xRT)ksA3EE4Bg$<@z1haHh0*Xr(vdNMsABLuzQ8M znENQ+Zr>2(T5Y)5%yU{a5Nx{nv3=sOg$AYxrwKkBWef}o)D^8>0ctBRtjel4HyAdb zCuMlAM7PpheCA;c%zX6+$A1Y1zs)J@{}nYq!EzcZ{p2M!m`>k`amAdIM6wOS#pybx zvhanhY2pz+i>iVK05NK(NvH<3u{3`od@=js^FWU9#YyY9(C4xNu6JkjoNZ#oJPrYd z=C=96t)uT@b|;SPB;0!u4qRb*GaYHZYP5WsV{}KUhC{+g;T&q0yWU|7W)Z_8^+4(_ zRD8`X1>$E$soFd&l#Jx?4Qw&afpCEu zJh~-W3}UY+34O$^#qQ^%-?Jd{O_%Az@FNAV1Aodk#4XR_ADS5l8TZ_y%yBBzJ z>IQSxgaYk~d`T8^&)Rqs(cB%%Olqu0;aFho@Y#ZUsrALN1{^LQcNJIOv~zsu#_%WQ z-dPtBl@l^FJ5apF$LEkaA%a7;i%kZgMXxALF|WCUz%N2yYiKxbdA&Yut8)EjCc9LA z^V+7|)`1~Z-{G?@micBt?oa~=LD}^$`aPnV8$y|2O~=5($b(0q=rlA-6vDslgBvQY z2)~mB-}tWpAh^r#F6He$PLo>0E)qfF&22lvjmYK??*$dD07A7&)1Io9!qiX|=E^P* zc6`iYyX0lJG$F$v|JJ;2@kn66orZHc?UU;xEIo!?UR;oS0WR-x5A^7xjI_En>FImM{jI0AzX-;Q8Tv@CIgZ(>qVzsc9mvSDvh zp|vZeMEp9jK`NeeSz|BXG|PAo1O2Zj_4!cp)vY3Ap{0Zv1?CK+W>3A|(F>TV#-7fL zu;vs#;@ZCVW8@OgXxGAIita2wYYr)>X^#%VG$)m{4$Hb2BXA-Uob8C1vQLNjjmR(= z)!C=86`R(QK2^)cN1`w;Pg>?;Qac0XE`OU3rNsWuzU~>Lt#y%U)!Jk_o&>e8!d4zR zeOljXO;rlwK1=PVKHKO5E{|9P)rN_`=~V_)2g@GW{YOL^Jw~=oP<9g6S2lXI;_D#R zGlxXC2>_WV7?G(hE#r~=Jf=NY>LTj3$ZfRe$3em~5M$j`k=%w3>_=#`E89Kd<2>(u%MurPHIty|VP zxwd0gmF?5_Se`n#7^)UgEC)Na{y@ygbLwB1gbEW(}u) zb8bgMg%8+^9=UrhMfW7GM+<3S5CGVc>!E;(5d5O^V-fczYZqqYqn5bt97Gtr@l*m~ zeZ>(=-$zN`^ng|TamzCG`^gx~x(EQdH>l76n<#dROpxpbipTD(1PHesRbNh%eJZD< zE=VYL(~<*fr=Ga(i-1vut!vt}ZV?aKW;4{jjeV9Q$9e^EhXBxEkMh_7d3bDb9vBYx z>%}h2j+>w5qIVerNc18ARyRo4JF$4Q79@PweB*|D%X4Wdbta|bdYk<}H7`ckLE`V# z)8EtPyyYh&SHpa{O3=0E4ag%LJ@uX~_8WE(HI0-2){KrJ%a|F#@~M+R$6A<8l9G^v zldpYaea3o8$0U~UjO~O@ff$;(>NrKUAg!i=H^K$EJVqP4GfV9l=HRwv(RH@CRU|Ai zsiBQlkv(JId7qPa(s1#5oHq>9%OAEO>>XsEScE8;r2t;M-S0bjA7P_xX`wZl8bS4- z%D&=QlPUd8(C8;sq1a*|M39Z1O==1DgWlV(#Rg^RPXsw;L5^M?muGQ3Qy)vI8%x|i zJOi%8CL_77)Ww~&CVZ(oN5zE?GLFf`>>rufOZwp6-zon;orU|Y0yt}!L)feeXN5ie zn}CMw0?|oNE(=0&30-r?_&@o1u7zFz#{&F)dl#BQ+M3t$^y)Hp?TjwN!=;UQrza@Y zkcJk^mU)cphiyfNE z71CW?ijnWFS+n|taV^1Z@NCje{j33&)qIgYb$?qq)E+AOyisQ zfoSUypiY#$MQnZZYH_x=EO;$0;yb*MGoehF6Ufs<`DM)vI%xZ5+E~xCBIh(-(n0xW z>2z-y@G+X8uB6$=anBamuaurPmh~wFCkHff4s2SMUU#k^A}uCYG`q7S3++d4dQT{X zP@Kxoul@)(s5GE{7n@p(Pr9NeSHsOw-|ZvhhTRVGMkT9Efgv;ntG5*?BC z)J*FhtgkVE?{MM9Fch5~wLoBY%r^W~AmUv6$ZqHa4!v$lUU)1OFxghxJIj))45uz3NFGntlTraf|*O9 zHz_GK{4!bXi;}Oa)x`9W*1Zkrj_J3BvlJdE zDV1F*b|UXdScVVVSzoRu<0aPlP0W}sFb?|Kp<33AJWH<1*Uj8d?<~ZL$N4?h;G8s( z2A-j+#7}=fDXlR#X)QZgKQOmf^WE};QD8Iz0ol%-@I&i^bFI2cG8wlcVxh`9bq+n- z0@rV!*-{!-4J>yp`pb-I}BTG+Mk>}M@nwb3O>&S0x*7?EpmL2Y) z@AYAb^1dUPJcJ_nfoIi@jP=c=h_WddYkuAHIV|VH36nhTu!%@;eZX@Mef1=QDKpON zw_nsfXCcRZ^=so8jR@6T7L7-nkdsPk zh>97BvDZ@4_VFqzG`3_#=BGzQlm5m@;}GC^tweyM=7q^aG4(;E+XQ`l}Ze)0o+lehYAW-wx@~3D%Osr@6Qw7Z;nt@pv^w_IAF1 z5$$U;Nyg8Z>?UMT(m$(!(>5>PV;b+zI|AIp3du9~Z&#poNPOMVy@fc;8weqWt{=F{ zlFYZcNIbcq1=fYQB-eK#r+TwyK%N>Ew|w&LC?f9eH2VAWjj1ya>34@uzF0Q?#VEd$ zL110m;gCj;r!QYtofTZEcS>^5?SFoueRydF`?(c4EPlCw;)#Mbj4~ywub>0t+E1Qr zMw)qJiuP1cyYcs3bBoIs9VKiFBTT;c01J~4wRW}hE-$srP z+W^zAV#NoLd7m_Vv~+hW8I#q{s>0H%XC7d})NBkdm)+N{^(WBe!!SF>ygK%=2VMRw zi=WcD@c7kc<0)Z^ae`QoohR@$HZ@n=EUq7z%HgQEg#_?aZ8N&pE$-TaM=I$ zf+qWDW%NX@>{jL6FbICF#s1}_lp(s^$+6x|d~z>dLQFf2smpCcpjh19?Iq^-1$aiE z70}1Lw}qwr__mTcZ+C#t5TY5rn85aR7|^ck!O&Zkvnl5ro|~c0GDF z$(dLWJPnuhy(PGsRcRNfBf=_0{Cam3A272`9!85qv^i((Gk@!8RJ?My5?vQX!jr^5 zmAF)iLV$8eKZWZGXVCeckO4!`i)666n4V__MF#jRZP>lEez~N} zt&|avf(VQGpWNaj`^=@k9@)6ANg@u+TBI?}{`K7PLynlXpQ!}DB(fxLkeENkvSK|x z6^)#wtkz51KmHP#19kT1TXt3qEb!7-{gJ9H*#{tU$L71R+$2z!|4NUZs0?GL7oEzg zF@b=S*11BTWLnap0bRJK)uE{toxFM6{_;u;<7M8&j)%4W;cgyi-;^F8l%8)Vi{AJ@ z5z4<*CqQ&2z6`*@AD(^+*wCNr(J9;}oc|E5T&q;R0zVc1QMdk50+x`$4?`%z&Tko1r;xV`j2X&Z#He)WLnUqGKW5 zA* z;0!`zM{P+9Mu<^!86j==Kp1V14j%B7>X{7qSXSQSe{>sU;xxoU6A7 z3K{l|DcjN9j#t0tbYp*wQqotlIbH>hUyV;m5(tX65DaxQ;Dn-zN4#wpFK=DTcmDGR z?6i?MN>V7c`lJj4w+5H|xnXteKq2VqxaJK8fkZB7axEsrgNLF#eDUGf&a{$Yo#x%;LGc-t$* zxCAvx0BAs*@XJ{1{=PvqfQBHGYH%0|-=* zqH&5$2Di{14OauY1xihSP?#a2uKE?W7)ckBmR168;=r_TP=oPJ>F?cPcl1Bv!Mg=x zHw-H11c-p%E47u`Z0LbHF)!|||KY>{m%Tv$r;*%;eV;PzZIl3{h0Q>iGNod{*&62~ z>zU%{N$ye;vE{S{RzR-_C4SkgT@_v__<4v56mKyWplzLiN1IJ_uBUE{3<>b7F z$JtlTu}IF!E4@=7<{>aGDS64@HQGt~UH76J4mu1G&7_Y7)G1cCaPvgUG}8yOMzP4t z@AUB5w8Zxs1M6qrj`dwE)+vU)PL2o}N3LhOF5&lnhZ(yi&GhmRP&fW<55R?oBt7`ggMn`R28F!n z=+?dF#!W)8c#^%BNAqbQQ1xbhJwPy`*sUju*XX$|_&?|I50`qFQHCl1InheJm%7hq zGdQ0LQa50A<9-kAgFkweVMlpEV!E>r|1(~^tcHX&H*Y}@n^9M4|Inr!FHL$~g~)ji z0RGXN+E1XG4H86P@dK`zSiT|46j8w4bPg9ji*RaTWn^lN_T~Jq&Ilk_LsK^J;#02tCK&?(!1 zNf~mMo%Jod8^;E1*WUhD)!^lhPQ}2M0~-yNQgz~!*D`!T0RBHad>tLWBYy<=_o5dB zfuUYFuFiPuT$nkQ#ntT0)LxySypD7L{mIJqm36d3Hq*2tpi;SDy4q#Ba@CJ#x+?9y zIMTh=r)<}LPuE$WVVWLPw0YlPcADg|ZBb!X^D*z6x0ex3rAVL%%S}EUAuS}H}8+g9`K~x4n*sc{N*Rqo9@$s*E$E z?`ie3*8-xe(YdIItKN~T#_(*p3D@HW;g0mAG#S#S1 z@WY?BwJk=r-q% z_=CldIr#=LzgQ#r6ylRT_kNptGyv@s(5GmOORV)3Yjp@DS@5+xXZ)3)@a>c?o0l3Y z`#kt_XUdIe@*ooW2b?cifH)iEA9DE3QEYW%Hbwu_dA~u-NA<$_euaL%K2Dk?zbb^` ze6je!U-SCkzRx)=H{AC=|2ZaVHHg~#zsIUSj>PLS{@Gss^<@W!w(HyY-_Jb|VdZ+) zzmELp*!cHu{(rrQl!E^?wEBxZELdaR0a$GdLUkpwN$9yK0EFvkqtte``SD^6LbM%k z$*lDHDa_TsQ76b5nG!=kM;rRgKW#A$NUKAi15lsI$qLzL2ZCA(Gn8GE!{So(3n_*1@QvfLlgac7IFu8dinIB*_ z!ZPfQ`I9r|Z$(K1QA~b4QS#SVznS-uK7?}DtLX8Z+Slk9zQ5RHN6$MWpEkZcrOil6 z?u#gImh1VGzbr0@Ix6WK+>3C(n8(}KKJw7tcJIwss)SlRG>XM&;Aycq=4GDJI! z{1-IZOS{>>qvJ($h*E1(*+b25V}*Jnt+I^|fO8og)87wBUv*xns%rg_ z^vOG!<#3(xy{WZnjTM|xdt2%7;KhE=^g#j|aa-{MMjAv)mwt&4YkiYxlIa~0`Jh|H zCq7L~@Nv9_{VidEB?`*VaC_tXS>hI(BFiQTmL*mXkIH~Dfr!F;|SPS4~GXQYG1R;aoUhxWSn&P~Dw+NrqA@ZAnMi-Pl()pE%ZHPDccii*xk@BTx{}(z9?zhZ1 zy|Z-=@);es=QV(6BUo1CL6>O7NSU{8H#l^KXPIFtdU`=W20VdaDA~P&mp$L^pZFKTZ4-p+UHsF&RI#rYwde9 z$oH?cW=>`w$xtiGmq0WZjGJN-`r-Y$BSP=fV+z=AZ{d(7YJ1Exq!DLz)T4-}4TNFJ zXsG4T%N(#sppVSzmUTDYFg4-bLIGm2J;UU>y%>&IacA$ek)7~c3q?~V#%YxvGwjrO z4vP&`AGUE}DiJMH%*W~PpDI?2k~sPZzlwpe(}>QC!vV;sO6Caeah@svJKP$8T|U|t zFz@e^NmFgNt(ff(9pE~;F9}l0bL?~LmC5DAT)ZxRHe9^I;d2j*0>}UeEn)gbMZD8u zBi|t}ZQ=bgt&Z=Co#oX2`iRGdj}uru=#E^K^FA^J6}^+Vy^{RC9E*ZePdK=2kGYv^CUCDXa@zczetp34 z4^~Y^QN_a}OYuRxS`yY%b$^`urquWE2pLm9<#C};R(pSgsJb;y=<_E2N>CoFP0ZbUq7|q0ByGxBwz*sH)DQ&xMuqBn;uxBZiP4Hf`RC27aNg2x4R|Ud&b8eDOWUTS7N2u}H$1>SLo~ z%rMoTFXnXh4?{&`5pI!Q%ZdJHhUI{ZabLS;ZpZORmF#IV4qZtA86Y_=ybsad!<)VV#gP^eOMFWN7f_LLIQVu=){`+H>T7eV4Y&6 zKP1x?YeVYOj}0lD})vjYkHq@zn zd}7bHo-m|v($kWCd~W?de~|wAU1l*th=E8^Nt(B(D4xgt24XudF5WiMUQ`5_l<@Rh z^+n>I*z*Hvc}m;>)u2f}LqX3XA?dySA!m&kZ{^b`2xv6LP?LNurDF!d4U#!=R(@u^ zhDQDL1L1_3jUc&(&K3>=Ide$XD9mmaKQ#683$)&k2zV&ueP1JdN)R7P0Dw2wSclLQ z^7!Q$F5bP@dg|w5p*?$kR=>y&wHFxr>1&Oa*$Q*oG;^ZVsNTqgy=jah@@M?y!PDS= z+N7}(xnQvVv`YFwbuE6Ojdf#R9`DulV|}8&+t2uzu9*+AC8n&bor0yv>a-Db!5`*E z0yZb3Q0%KpH>`b!eDqC;48ivlH%V?GPPRITicfFW!=vO;uxyQ5A=c`6TI8wXF7KS5 zKwg|+xXp6AvCTCTYjH4Wo>AQG-p?jj3EySXye~yC*)>LH&3UvdDzUM~w5dRcIqzxc z-#Qc{&yHBqPm;?*G?;m5`BcQH$vR1p--s21XbNm}^s*;Ao9f~6*X%e=@(cAH7IrVd zljFdh@3iiCf5?fTAKfm%Ck$XQ4Y>nE*fZDS21nd42-I#NV<+ASnl5&Xib^)9v!l*3 z-+!Ol9Ck51M=n4H`S5rsVZLVXIszpS_s4@`#o(GiA$640nNtM_l;U{?%mYrYFp&qW z`Jgv)4IlhCzl4=_i0ofS@1%$7Lt0)y|hQ= z5alyM$Zl*a#imbG+|8pl+7koT6si^Ujg^}ca?C{XKqJx-QkU6xb03ooQA1ix&kSvj zCvzG{Wg}$NgCenUpSL#w7z|^%kG&@4-44#4; z&F12ZNdX;9wuiM$i(LyfW9!n#(0`B{PTC3{_(Ll?beRm*8Mj`feHmyg5zw*t^wu#u zb4~$ABbh!5&CH&^?o|?<+FIQCTO7F$pj9#OtoOcM4+m> zy=0qVNzmhMEQ#mHm$jO3Yw-Sk^}e-{FxX{!JG?pq@Bl?`nTYWrxQ>dSpnZL1Gk1AY z!%kq>bP8aK>p-!ca1i169ZgCBs(t@jBbi_3(xwbDuo}<^4d?tdKjQCh=-LHcy!~_H zpvlIu%il`lljde90Bg{uP8aiA-UOyTa&|qW?4&MD=bs8R$%nw%>F_G|t&*3Id9UpP zgY1wNg9XU)#Sn=V_5&8)GnzW%BZM%lsAh#4{{Zfq;E|6-zQMT9oOv5$JYt}yBDe%E zdN4&fJ}zSi*0%&AOBOM=a24SMF$+IQSF#PhjxKw^b^nTBIooUkYw|}%ju62mt#%RH z*lw^{jl`=L*j6N;G-bJZ!rU|4Mjvme3Jf#5l>zUwFJl)L489Ih_B62C zv03t(y1QokfxNxQ$W|<7ZJ!ebgARCrwP6BBFLzpe4~;I&x*<(}QtZa0n%IKlMGY&P z6{tt|d}7(^nizeZn4_p17!vdOt@<2KvtG~AZ}UXyA&Q_OX~kApB58l-$b zfh$y&XL^0(THvIHTPBF5y9lW24tNaomeZ*TIm_-S;pi$;_E}(H5TMHgC!}`i4>*x-jUurgc79p&`T)KiTl&$0{pHn5Pz{I8oc=A zNbnT3Cww4T)=Sn(h9rOe`$Sqb|h7H>rCOg7trcIaVa+L0>>=N z%a%uO)^yZ&?ds}F9pSL)Kd6PmM5ZyGp;w)@hi|jwP3+7U_2-%gpAiqG_dZy6|b@? zi=&iv_qOZA>l(oz1Sq?Qq@4Oy^bJOTh`<}Pz}-sVKI6)bqgMTlXMmfczXHR;A%)Y0 zH`5}NuPHEH{dlkDv{CZS`ja?8ODI}u+&ml329IjvaH-FWML5&TCL?~;kqq* z_YsR}8GSb}d$NePIJmXZ9)HcyP=u=^*0ytiuew>E(>WH^~mO zKSJBc1RD@*6e_5TRou5^EyCZ#?m%4z5$ z!*dv@K_SMBo6ikL;LxSru;U#ZDZgfZfh%Z79=57;ZSW=(t-CJ(d5Qqh!XODTys?{RRF4?lP`2 zyYQ~8l9+kY0EK#f)gk^9YN+v3IO0Z!S>D!dPldHE?A*b3Z)GFxIunQA9~UivTYG+x z%6Q!Nj1v|b@(25uMGVnGrViH>fuL;Ua0BwW5?^OT#NnVQPip7^#OAK$ywSq`j*7l_ zQY~-{HOwILK+-6^uZWO%Q!>XVgv48e0t$;M+Wy3Y1L1d`%kDBu?;9ixN?!H3b#Gxo z6S$`7TdhCXtS>S0rKC)ZbQg79+o`{BG_gj0=Uf!_`F{K%A@mG0e}kU-+;=C0dJsxC zsalr&A=Yv%-%ZaHpb7M)SD=;B*;6X5x|BlqiF<>vmU%zacy0aWrX?E=*?3?hNEZEi zI&jY(GCq>cX3zH>WRAX@@@t=PVfy7{FR9cdt&vj_#hXBiLr420&jAGj+V=3e6PyFn zzUt8**`hQo^$6nLv2j|j;nPO(UJJ`}aT)G~34Ow^na-vLZSq6!2!&2pJ=jGA|zi61HEgH9GQ8pxm%v;Wl{y>WLxA??+meFx< z>7F@U{YRDNd*-XmHx0c4^QMjpJ+S8n`9IlVEI>)I_>y5Eq0<05ZtnnHt24>-vq`$= z9&WX_BDGS70M}of27B1AmhjAqXqPbs$1=$1-9J2k43~wY@56Dt4=0GVuS+Vhiti%A&zLEhK;TFs>|9l3!j@zzpu&LdE8mAQUnA_pA0<_ciE}nnU>Hfg9Zt@&pyBQ zAQK<@Rl-qsbUP^e*E(l=Ypuqe3+NsVw86m3<>|NgeNhL=1YN(nk`vPSpFR6K^%(%c z#1KJY7$yebqB^0g(R_{4fun~2hQot+SlG__@NM1${!I)af|vun`@-?3r&qoG@A9YL zz|9i>yIfUoam8c*UaqPEnkD*Q<^NIr|Ch>Z^ zQ04>bKl19Y)Vg{-TO`a)j{7;X*4}9sCVNHo>eqKp?D%|Pk>I;hJblj0UwOp-d(5uh zwZFm0DzQY@mVcUh`TcYBT}MdbuMLBgl|}^`MJxmJ*sJ7cDnaVE+e3ssIXRD{G6~pQ?25Z(k=8AqTj#jgdBDsTcFdMG>7rOFFn>RB zzVmCO1%vfQUx;$KVWV#wF~k8#AYELxlN0rh^j(b}@*w71uV!DWqs;%zpJaCTIIzY$ zb^Q?mp})#2j95SLWbkyNM+y;beS$S>rr13+?n90152>yMydM}~vnOy_YN+~k;7fqz z{(b`fVMXl+_5=UhxBu)4|MBhLYW`OG_x=B_^s3_js{B8i0%-VuQY04uWGJ$H`WPEG z8wI{A!<+s%CapLnnC8x%+mB;aMt_CuX&Fq+{(_l99tKAr8x(%K?S0fDCc5gLsuz># zhzNE)&}%;J{OE;AUE6J12Xe!&hms-xAc3LJ(jT8E&G5c1S*d><$9wLsSYb6$blLeq zusP=L%hM~c@Z6p7c-Evd`b3INx6b1vgll`-b#Lk1cA)9@#r*1JeVx;sWbkDY)oN3^ zO3bCE;&+`A7PC#Fw6 zM6aYY7m1wl{9$JCZf+WHj^|2&%E26ck2|WjBg0?mw*z(%{*bqRg`M0Wihz{nY!ZZ#3lVLq*x$N351@Brr z$s0eYA|SmU9Rlyg=($YCyh*kwDGuQ(rc%39gh%wu$t`lOwLi}__#MviM<7s714$)+ zFk#64HF5v^mGdRN!E1UbgbDn+0@r>qTStCM=l<`N_xBw;9qG!B(%)x#|M#N*M>hZe zBcqTZzF^=UqG&y(d3Mun*o3!-WmOZ>Qk1W2hBSMjxNodugkd(F0mzem@s&}!Qs>o1 z630%UQIB;Ka)TK1mMyG(@PncDwL-0L%`WNOFs&PPYBV{Y?=;RuUSsg$0WzI`!OUNy zse2_IbgbUgESkX$tJrORIN|E%zad$!$a{`)mS{rmIV=oI2MNgxWrz0d$2%dxGP?CV zV3}FNXvt@Fbq+wN1_tp*UQ1vbLHIr3r&ci^YN?Gow!E&nqm9J9=X9%p3pBkeZwJ;- zvP3E=sw~V2I2;aMI00HqUvk`Yv+$0ep2dqpdfSgNc^VE&XLp*ARz#5BO;1(KjibAR znRp%Ff*;$xsA%y|eo70cr1g46^ROo>e6)_!QIkCGC6)USG4yL>)`!g^!;uGUo6<%6 zZe?A9nFO#3`@Jg03QA6@K&8hmjROvc)u2^ENbgt4+X7hWPyW^JkJ`619CkMb08&J4 zXCkN#wxeT|I3A5R&N-m>#41mQ$p7d$e}w%80fZuXijB&hqhtR#)8w%SgErl)T5r`# zA#kzr@xhqEVz&#{WYxz@&{NYrzNoZz&oa0jSj>_flKVRAj=wcbqQrmDkh zrEgV$fsC1RH*V~_BWO~*6F)PfXxdu0UesL|0G2u5kD_|8{ppvxJ45p7`&P3mQb!abO5L#0X94Uaps9<)#RYT$Pld+ssL9VZtis&7J|N zj{a*x8<6vvkdC$UJ>#V^TI0^JQ9(;A>9u0pu&!HYK%=u~c2AoiVM1PZGWVk9byWK6 zj;=;wkP-S-%H{R%@SIQDI@O)giMhtRhndC`VRIbnz}}^gVUe)P?A8%~oMGiUYGpJu zR?FL^>6g*mjvTrMt<%rQbDcicmAV~ORvtT%P58a59XUb;HnAVZi!Z7RK8a7NT6H~P ze`i`10z2N_y+bU;58Jt4i=Vt|dz2}Dbt7ud2CPWY)OORjV(ffk#nchw_6k&+#nKxM}=M|o|lMvL65`Xkr!p=mvy7BTu( z?RSVb?z0KhCQS!C9?$eXZrki>Re&dz?QqyTYDHc%U=EgS#Ufgrme#LXa)03p~ zTG|EBc$Asp2o`!fboWG5Yxw$}x1`r3QLHGGELI$45EX=a-MPQnr@XRN=&-Th_#)30 zlYO?o=UllvFS^^sCsPeu4rGW6VV+{{>}E5V&bs-8#i-*M(|D@k9@JqOBdoA%@x%`tPYX4Cdf8dv*;=2e3k@fhWG7`c z>x>TN`)p0txc@Dya_M3?#}&Z>`=9L3jPUNU*9#^w^mtlD4lqmCAOn2dWn=M<$jpDca>%XEZ` z=5?ks*L_OX#s7s_WafR`Jx4ES)aGa!zr3+xLpU&&=bd~PZs?WK$0)qHcK@R%ILtOq zt^BA|dMMYpcNFS?Zh2q6{uxdJv6(s>;MpUmO(Q~Yd)Kh*sNIVam#qF`l2kkYaKg!< z(8GIEC(rfoGzQB|vL4Mm*WRix|5$Upf!f{OtL?TPhxTI!oh?P;s#Rj6dYNX0hTIoY z*N!2>-K1egv-9D@y%DFfDcii(j0$y9{*oOD$`5oX(RjoTV!)?fap^W~+E5dllQek9h?fj|*jtPN?r!q=ZVz)`zlP1|3C6&64d+vqErp0tmoqe>Dxjug_j}mHZ3b%Xh%NpBx zmeq0X8q^5Chx4oN3Uv`Xt8zw*a}2Rgs9Eit#fg}k?*so$)dLhw0s8m1c7k1t1x9VE zx{*5-GHe2KV3V1Tj|AUSPkx@OSia2#8~0=S;f`vuAP)Tysm5v+A1sqcB7??%{`8SK zJf}NkHKD&wv^<7hz>}TF%Jb)J8R8d?OJe9J=eDJ;)nIRfW^@~aOnX_>Ey3wyp0v75 z+jVxGr@S#Ln)Ocs0;DA?72Y24@t*}T!YcP{lTX+(4^>w3b_9FRRLi4R6RO+G6u9;B zP`}AxIPBtfZ*n!3!WUQKb~s>#%xxup=gad8^NCX3f@-M4kQ@o2Cv{aG0k%3UFf@c+ z0$crf@#nK@H^jvH*JEbm{x{Un5}VUA>t({e*%)K>aF$A=1e-@0qPFjH=$M~tOYmKk zo#PO>S-(esLGDiuj&*I{K-T!~b%tTDLHnIX1Hf7)9v887g6|c$;|mM3TbM7nWkrx1 z)F_jVuv9^t=iKoH>80J%rx{jK*B7HSg}sjEmj%71hg!o=UKQCXc{^%6kUH$juWuj7 zFYDT{)-ySajTN+4(b0B=fAMhH+2Z0EhX)Zcb7fD%J`7#ER`xohwdPI9 zcC4U{k!Ac1ss2p{aE(7$MH9bkWn9FR;nMuqI7*Q@W!YP!g_WLZ>~$*x?qY?rwTaiU zYPqd8h7f8v+}OP$Cuo{D;ANyAX);H(R7FBU!`fWl5jX%Gzmu9d-gpw^sTUjIf3om0 z)Id+%IyxO`KRa3kUrs>llc1T6tzbo<;?0_Fg?`dFXxDXsk4{BOxjB zgWk~PscN!}?NgNx6OyxBj`E&rlV>G4lTv+~A3%Tst;nD{yZ><_fL~&Do!hMYfc!eo z*QyFNnyod<(Sw$I*6i?Ee)01IuR7rVF<__ay%?2+URFtnSjvCb^s#*AQ||a>CElg3 zdc*$z zn3lc5KIu>#+3%C{2i;EndlZJh@4y;n5%{-1PFw36q`gzP&#Zv$5dlC0G4LuVtmahS z;C}t*PK3v;{C3V=fA39`2lQK9@Jv@S*EXpFW(x~(9K)Mqww7Tw4V83K-z>zD^tI5% zU+s{E=Gpobac6wjM)3;1t?)A=H^SYxXr7Yy2y8XEE%rTc2z!0_qwhQhQ=3gwmFAVC{X$zm6$(~LOdo;rV&@+PZ*ZHCQt|uUG1(meQ}|` z2PH~ZzIlxOslf*_6z|ZtQ#!f#mV3w1FKr*&9X}R*PWB8BB5yqWE-lpB{8p4^?Je$R znPRsKwa=>|`X&oq=0-*$CDHWUgbDdUs#{4(4Im!4*!_0}A^KyF6>lc55=0i8IFD*>Y;KUpN zfM~*|%{?+)$fNuCm_#!rjtQYW(E^qzx`S!mCELw=ZEDO4(a!*P0w0I zii}ZUsAqs{^xi^y9Ev)V&(Nu{Xu3I62=!&wXz%yzr)C4I$Yh)8 ze>^$G^;BeR<9o(L(xbN;BnXK3cSLIpTPItDNeuC$hzy-kdYBJ5Ot>7rPWT;SW7500 z*a(W2llv0_&pW33p2O`nmrS(FEGz6UGfXM#7vZ19Ptn-**+>1oZvgpf zNnctQ-#xSYE#eWaHwE~nK2o!yfWJn>9ZZkVQM3mCu2 z_b<%=qX^b<2Q<@!>@O%4ytDRX{^E&=hn1N&)7 zEXlv_5W^6(em#-)g?$N|aJONc`%iHE2jW$8i67Q;t5J=2RVWA3_j7A)x)L+sp$prw&~ZSVN- zOA)3IfUPANo)cqXNiDr@4raFYPzrNDjz4tjL4K%xZamcrh;p5SiNM|Ik^IHZ@YzTE zKJeLsg+HG*XjQxwv)Q zZ2b=rL5Q12575@ku88xzfMK?k((n(m{lWS+x@njO>1jM40R&;*%XzWR@3_TG4rmWR zJo{Qtx0aBSS4@XKD_GXaBwAS^y2pm+In1WWiiTlX1A5bBA~dl?KHq`+i&u5^hb!e- zuq6a)XditrNFI0BoN4}ZHWi1^6L`cS#;`55RM4|ITkx$lLN&}?Lj+0`=Zy6=nXJ+@ zIsU>S=QQz%^)`-8@ClNY+&^i*RH zT5~tKu)V+Hm)#uH)aDw^+TM45%WV$XC1|gx$h>WZeKFx_9MwHNt{ISP!Nc4l9JRWx zA62VV=34Vfa!zhZm*4)8onOcYfytps4ndI(;UJ>vyL<9xU0E-gj4K9OrL`tTiGCK! z{+0{hS_Za--$=(MP7aTNx2X1zh`DR@WeOPqgq;QBt%_KiyJ@V+QT-9*9fxP`q!4-e z(Ty^$L(X?XCYeCk293WV%z%@q3P>Dtsa+~oUEa{^aoXC z@!hC#ow|Bc`~j>?bfo<~YU!cYW$W#Uiuzpgh}Uqtl@_RWm1neeU7;naYd3cu$k$`N zyVHuhWaifLB}33;le_3>R880-tr%m2?H=x&)fuXuA zF-NjUo!6jtW#IhEw`wk-LsvUOgwf3{2#4A&M}q1;mjNkC#Pib;P>;5Zxj$+Ra_P5na! ze9ikZdtA@T{0oMP*m<<@G=)T^brc(*hhMuXlDLp*Hxo8JwTu}~*x`kmv$uhX5PrjH z{BB$}&017=(2_MuekP81&Q>L5V01@3`T9;6eqhdyn4a1kt|GmM>uL#EuuaTy{0y93 zDi#q$Ucy!Gsbe(^(?2>6(zqh%=>z+h zKbY0it{? z1qZ?~*=^V;o!w0M+;+Q)14g#5xt>G{2XCqowBHF*6+==*d(P#AE_rU|OXGi5hQJX6 z*Z6l+WPeFB$>EZ^VG3X2h0RSxH-K_75$9Di_?qkXtMt5A6KXDAnSv8CN6w*FLo@$8+}AEIIRUsLD>c(Lkg~7MIpgKYvWOc zEDh$F==eWM%id*`36i~^=x&b)jZI16iXyNAn0NF1{H=G_^ntz9aZP?jf}ZKrO&%Ne zSeXI$ETTPD(0Y|FE?;Ax0ESp5^k#3?bP_@x;iOs5J4%UF6#{6FHVq-)-d*cHgAuq& zo-X#4^vv+=>iy8|C>-q?Yd>-S#sss?J23uCUdGq=qF&X%i*+^pK1Vd{!ggZ#QU?G4 zKaM3^08?J$(FS+)3qE1GInZup#I;w`FKv~pQ=0=6DQK}oY*HBEm1c13{4UrVd zW1^1?JMqhQ%9HX*!5LtfY!w2pD)h7q3vjSAKB5`B9 z)l*n6nwCXronm=4nli*g7FwD#@br@}82P)3MDU zp7eAh4R#9jR1J^T~ylAG<#{1r{SYgoc+iwsG#BvFw6@wbe?|vWaW^yYNi1 z@A%LMfm<>0U2W$htz?kbR4i%884)Eg9IFQykXm&fp&=Bmn`M1YhRTxh#b*kRn*_Fl z2LQYYKL<~Eu%8|Fm1t~7y{+o_#l0Nbccx}R2%&(^vXP30RBYa7qMJ}%YB^9FFq>q6 z7hLWu(pUaGx3;#L`pN5nIeYalCt(vv!t7=v6i)%)4MC(;j)Rt^Wl<$HntS-&pG9*_ zLzXhz$MhKnM{1YoU7<2-Z)1d42&{jA02t<06plIv0{1(qda6$)@23w~mIgIGIAT7_ z@q1v&&M0VsJPik<8leOuT_CW-?^B)&tV_jxj`wvAH>9fn4wG2eD$5s(6$JHPH<^aJ$1P z`k*NR%~L{A{-I6UQRR$Z`_XKiGJ93sfC|O{Z3%$J;L2@&x79lLdrvd0N&^m5&HkL0J9YK4F)X!iR&>pMuybs2s{$k+=jU&>E-%F&?uslhIQya;X&K8vo%#Y zgdc)@inCMqE0{YIXKEKtO$nBTSvHz41RR>AbLEp`c%ktxrmJ*v)Ytp!(5YK(o;PyL zYsYaP71hcWi+nk-O1^nD#H$bpdNCn`!3X<%cWZERcc&`Vlu!S$mmNU1(_D+T<*D*E zT4L8m-Fm|LT`1u7BhPR2DaYW<6o@{PCfeqyjU9;{;MV`d1Qz|g?az7TG{u1y7t~X| z5cyOdHyjIz^Ww^uhorCUZIHv1wQB5;WZL^5YszcN_H_moePeS4XYnFOF*r%J#y*l%W=rhVxQI&TO%~uZU_) zF4kyKmjsxfh?6-v<93_)GIQTk0oqh#>JCyl>D;*XkbiXS{8sL&{c_d0odL#M%)lT| zx3cg53WB#o*P&Gv0R1n|{lCHHNL4aQK@fl-|6c%cmMA>GZaj+rJ9U0Ix9@G+z z+irz!(8Q#u&%HhKd2mJRzI7Od#2+kswO>9v34QPELLdRA>y!9V1|aICSBScUZF*b!c7=L)gWT&zWR2^d{@&41 z{g;{ED9%1+0+Q<$U#JfE_ONUKG`ids$EPr;81MMnbGb8SUFKwW>9Tp~(%W-&s&da* zxvC)9V213GWVpss$f@oemOX8-H(BN~nLg5{(U%}xGOL^00N8*m8Lpa7X+;VDftgii zqpWn=4YDxz!oAzEv{gwj4Am=)3Bp0-5|-8D(;eWCc01J*91b6c@cts|53jKG|AN^8 z*!>D*{{y)H8^r#v$NrAtf8pW(0j5v9j3HB^uX}e~HFqxnG{}`JAHaQ+SN@+y$iDq6 zjDzdrx2&Ahk2FG*q&IO`&uos>nw^JOYPVj!P6PN7U_T5(4j|-j0ceU57Mdkl;+!~i zE<7aALFMMAFsHn!IN;m=JSW>V@^wpRY%+Y$a#B%@r(}!CXj*fmU%~}3xBIjpwbXfv zv%v?0;DDt7m$>|?`5VxB&5$_v=lr**upS#B?zIoY0$XMVx9ZU1yWAx8hq!)X+kaSj~rY4D@_}W+%9Yb`i z@RyWtH_+?e4)#DiK4n!MZl08Bb-m}L{0&QNG}{{{zpByqU&(>o$<^IubzFDP z)7e00Uwxgi?Kr@F_qm$^qle<$S%G}7v5&RbXlESQRW*o;4h@_@keQh$yu*l zwFmz(n=`A?H&WJxd_IbZp(&vFS}4t2qxW%Ti88akxQ`lS=#I~hDg6)KEg$lIWOc>BkvcE%E*Lg!z~u6*YI9;fkwkW}te9Hs1g z9#)?r*zE#>r1(EggA}}PA|%CG$!0cU^nPMiVGIIQeg1|Q3}*s*<7D$WiYrdvdGxqXksTPkBP2Y|?^bW$>j?pVem>1UmJf zlG2vqSFb_g+r8T%$2tjc&lS}Zp$nblbf3crs0kBujlx=~m;O(fwgEIBr8+~8C7zQb ztg=tYE3b5Ig9_R`F6r9}XQ8qtJ$kxcR3p4W?fUJhitBNQ;$X^1u%PRNToZ_In$2!z zcCw|bmg5U$yQT&DB;`r>M_822;=7}_2E{z_1aGPS^!Wvi`YQx@1-BKFU30RV(5O4` z%%ppB%Jr-p2X?;^xv-Vy^Y#MI<@55bmD@1P3{i=Ow|{V);2yHfXR}jnIPzCDui0HV z!X2%@H3^!;+YJ}I!SiAqRzBwU&<{*+Z0Q#l&EuJGF};Q9M5q!#D9wLM6T$SDws%Lz z{rZ#(s~1x_*B(LVv4gYbmV2+fAHvbMRpq5-v@0qmp!@efx}BRZ`UAfc$~QOaz@@St z>qu0A%U+3@7qNa|qCBVB6iC`Nq>`1SmnM@h4DZO6;*&qhlkz5PflfP}F(#(qyd&5zz~Kj1>YGsfRC$g(SJLC0ZOoH4S= z#EK3uj5)a@GvZoO?o$PN5gCyk7=pmlCNBxn`|AK6`yP%k%h@DFRRG!QlJq4_etGTH zZL5(!V#M`%j}-ao>THATkvwmP1!z!@D@yk8Y_euHgQgYxc<>bQXNhX4(6`WEn2&Pz znP~6cZ&KrUs?>1ko)&k0FRR6F-;0{9dmfpYUq=o_>mTCuj!?b_de{hdEN7pAtfHll zUU@Z{;C#TcalO>Syja#>I;nun`5fU^j-rZ=lc|qVkDz^c2jLn_{7J?7l5Q98_arp? zz{|hsCc~Ma=GejIrFUOQ!{$!Xq*jTDN*F=}8$Iigb& z{a~C|T@T=B26&30Vsh%JZM-}8?a|`w(SB?e7d&lJh@kQ!EDKpRrT%j`~bYPIr zh3Ctkm$}w=V0KUYpvtW3o;jvNs7durgjqLY$R3;R7j;il7CY9x=OIqO#@Pg-bI$6M zS3(%F<0VNda-u7xwCj7U`@nt90~wY}2j&ciWxg8Zr`@HV7H++4FLB6rm-gy&r9!bz zns2K$s*w*4zR1{SXr^g^f%xsKU7&~$Cfg^7=U!oX`DjU6^-Tddimoh7mO`qIjwDRq z3kQU6GET@Yi<#Mv-?rj_ddY`Jv@W7m_}xBH<*c@Y$hWq5UFu;& z_xd+>e$9%7IS!z7bBx6u8OAJAJ{VrB?a@+bd=Brgo$YRM9N5djy)%eg&@dYV%}rde zbHNX$OGG&0QdTUQnkYn%axgDaw?256>mKbKK8<2xe=N zKKqrN(jeJ8;&7Z}gyS2SHv*r4+B^Y4Ki-;!PjKTs_da|X`3tIM59peIb}p4BkQp0) z3#Gj~e^BcDxT5+G+^;j4Zu25RKJkajmf`up2IzoEd2xd6u6MSP!c)|RXrWgpiT%KJ zKH%QGq2Ki7Y?4k+L4+8I1A?&?N063X>5|+t40^F{{+ci8yg{P8&$&eB?H|IB;daNK zj7@5#Lc7M6kU;Qz5Izf6i~Ta1LbhS9CnpM|cHxjR@w$LDN*}pTP1vhOF5I(FM_sAC z?`R)9HrVr88XVlGHa(yP+%#7HPrnilsE8m}{r=bqSlx1Tz9Rd_s4-!HkxqX;)Re1{ z!f~Qlsqq0nB0&Cu^VGewEJGd?*1sBfdH$9pI4?5wIiVeeVq%4x4d94czC$*{^Es<^ zpIC__K2H`NLCMJa0f~#VA%*R2Ow2}5q%^+ik#d1Tw*U+9-7P7#IUmQQ2=6A)_8e{! z+Zx5ehXK6LU(j3PKy?(BR8KWYP2ET!pLDG5-(f*$ToZeBQK!_s&)*||>x1t-U=2LJ zFDx`QZI`b4Rmn3E1_q>DJPOEV_&}Uk#@A^Lx3x2`WV<4aI&2?37CRX`oFzH z#s=9g+4V*>zs?6OJ_7>T$>D~91X|v*N;gviX?-L|W$m;`QMW3F#$@io)U^-@_52ap zYjT;qS%G^yd`q21lXwB$>+7_72M>(c@wbo-*H4B-6;~J-h#-R$P;@*hIYHXdlNxy* zkD_g9sdduB!#}Ech4k=jb(5a_coAAI&82Lo^_*+N)>FC161doq>+Uq#CwcB;z_}hH zw{eBXwK1BayeDfF+3V-lV^>N>j1&OSgIPWgCh57V1PSual3Ae+b>VN@X_iwM(|t8SbX3vldzZ|7Zes9`Wfr0hR$PD|JE z);l+=?8dS`<-p8F0|LV`kEGj-cXnZvV-G{QTM8sI;xZ~Sv#37+&f~v?=EIY8JPL8Xd zafNX*xSLI$a-MD#F9--2HsON7yD<0Gzs`~!6)^$GzfKzkeVq-#DGB2e!^Mz<*NC0c z`Z$-RLB-~&Q9!U(o8;sm%w#$ag8)n;$Umk^uXOL@KekJjPyjeL*JzpNL&5B1s|4{# zPCeB)grCt0IBrH~V{KcISNpCp@R|tRt{smuFlVzoCz7a~X9clmDt_^rG8T|e|84>a z(!+?#!)kvkf0oC5EDc3S_n*2WHa#R^VrJHw#d%C-)-HvOpeM!ErJ?7WIrV8)N40=L z{y&YwE5pa+DV%cKZbw3E{bp@mB?FwrW=e`4Zg{ElOBfJ}tp9CtT`f9Q63APtG=jUY zTe+D84rDWL?>mDayyBs-eoNBZAjoSJ4#8ENbsZ8+uzj~x_AZ!?6pv@|bji6B{DaUgGV(0WXU6;aL`q)JV0_@BQa zR*7CRdgr>@jYx>h5<^vs%gVLvaE53Kj^9KYqXE&6sV3my5U*IeY8C+`(cVqS|7Ii` zQyW_TFq-QUp@d=KLp=yHhq!2FMdx7}_-wt1C*6>ZFGNIVcr}X7kkCd@P3$LYR;>H( zZrZaFRg)&rUCsuO*?I|Xjx{F1TECz)TMmS4kirqpQ?1@R{H6 z$Ml41LT4@?P=}-Cf&`Be3VaS?YtJth=qi^ZIsCvcp2pR)y_u9F&ODd!$8B4CjeFsh z>G)BrEf^kedTU)m=9SDt4QU_n%bU*8Hb^u6l+Goau}#k(=em4Ag{2vNo$Cr_MKeW( zk~O1hH(gc}^DyXCx5UN8qhuBhIrJJXMt%%tr!JcIc ztlwj(1~h_&#YfpgH=re(H;fOJ?|<%`;nhC$S`~B%R>I&||Bk%*MB8>^>fv@>Uz&&< zTy|0YjlDw6Gb&q?hA+gMTDPx1GUXM{H7&cwevL%Yk7?I9JrJ>iz`Nv^HBwh8AZQxf?nuES&8T#gx2a)F&)MoJ_mU1x5<|@-@SE}t z0i`WZ%p+}@K9R_2nD^$5y&IuPWyF7#)lNJNPM+@aogYI>w+Xc-+KJAxhe;yVHr?R_ z6xYU@v&Ix}y1@ON<3lH#jhw$c&dr?NuOL6Z32lgZ_depwy()o6G2{M zJ|yg#)BAi^_MmLga$w|oBd8>(DCXVcw6bY&yju*%QRHLa9S%kv>f@|^0r7XGm=nSJ z4XM~DJ72lU6ZS279ObOdL?P3);y*qsJ;=TTr2Q7zQLhzo=tHX6k^Awi9c2=z1Qp#_ z?8vNgorVtLLCp(3Tsijm;iDXcy4u6%oJuM?f=4PNOH$9sC^oFWIpk6}s4a3<63V~Q zKYD8wT`BvU`i?npq~yv27UPfh@g&FBJ(4XA*xhYd6_j=g_qcg^4^*f+l?{7;La{n* z88WrkAN35#Y$?uw!Y9T{hy2p;z?y#doJ#(;9VB;b zA;5XR4NDe7s$W=UTUNe*7m`3~X4ET)zbQ1Ha~P(;A1!)({8uVd+L{I9O`nkRqVA1?qUw(7UE{=8PY zhSHs9r}{fx2?iunFNeukR=bTZCAU7+To9z2PkJ{C*l?&*^72%qPQZMq0H3G2L>MXZ-c!85TDfc7KNohoYj}hNY?slbxRzGgL zi2MPyMn6j6dRrRgYegO3d*V68@mC+d8+_$NUfoArd9MF4Nw56dfamP$CB{NntgJE7 zhl+fXEXZoy(asJTsKs`5>Ze}_INk@m0P8I1rj$g3?E_WWhVg?ZwBe{>tLgR%Q`^I{ z?~3}PWDhm|c*U;Y5#;HY9(A+PmzqiOB1h;b#lQbxLie0?{l-dpj((-r{q-9S zM4;vQZ9fqn37!m%?Lvlx#N>+H^bpk4SproyC;&o~t-%`j@}*w$!|}I&HbM))qj`0_ z?XHr=zPZv?!wMlEnZY!C5DlzwSDCCy>&6{RIou26tKn^-cX|yMJ33!3ZKpDpL=|%= zKBG8Go|-VTGu!UbG=s>n=^7ep^j^Araf*ar`x*@&1> zijbM{jlNWYPzth-IR-tqh|?g7!E7#<7`KDKHW7VEQ=?+<@QLBG%Yb|fMk)RrFDd5R zd;ttM^UM#{nD4{xhJO5*GMjw09REl4S=Sqo4Kbnb!zTOp!>R0_TnKahd}C&L>I+IE z#YjzhojhH37GyLNYqxV*he_3^ zZq~@64uzU;^Q=4Dj|yxgn53I9pCi26w9{Da@>Q$&y^{(8Hix+%9v`S-M{G5#@s7?!AUUEp68E~$bon=emu#FH*o@{I_{Swb_&V^ILz5cnnR7~ZbuBR>k$mSrqRUUScqpXuR*ugG`HvS zk_u&h?3!x>p%!XF+x9va_I>V9i?>^rlh#$5&f7n&CTVm5*RCR)81vEL1R(sy_0o`c zPmf5m%Po~v(_{!0MUFMM)18;eK4f_d@n;NN;%SPUE@M-jWxUMndjbbpEIhWVwQx^t zvR#<(zGbRjS*W5hUfEKB_mBDFA38GUOXhP&Eye1xdP*$r z)2X}s&r)@5J!&`$Ym}*v`ioektmd^6>X;ud4^Rb3o$+rSO?_BgI>|E9O&b#7x5h!? zUeYCMall9u-y=MvW_A}_YFK3sm+@IrPMVw{qqf^LP&ECDYkQh6+gFtHu$8zInP8Y5TSlG-{oc4uRw@0-)&yDPn8saCz!P46_p0&TnD zo-;ujv}{!6pW$OfNAM{oLwVu5FoaUJisZMzcP3mew~4~gA7m@>A~Kv0yT0_}wxJG5 zs_q$D4LUo#RTBwlVdMWLz7jN=WJC6&ycwBCeHee_R?u47LR&s(fRE>{eoM zd2&{BOYQIuWrcSKN%-xO#wjmT{h80st+0Sq!U~sMiu0axG4PSx%qDKx48tX>t@4n5 zES~?z_ya$Qrt=8qjph?&QXjE0>UwwXu}9rV$MfHGgIS}yxh+o2KgYzWuA?Q$F&fYY zXl)!Gc`ZeodS6E)Xo}f6-`Q89xxSA~*J6p>b=Xp!X2bI0)at%@eZ8B`edeX3oShoy zkNA0oGSt@0S(ek`@BJdV4$XXO%o*ep=d`~ux_J{Y!3oE0)fg6U0ggfJ3i1mzz?U`B zTve(2ko?PJ9}V&gv$J!h)BCYPy?-Ly`zbw8daK_~i0f_)w}Aj@m~ zz&BKTicPJYc2ol#yF zT^Hy*!#y%ajrCaS)ChOf(AeQc;Q9!KS;_*jixq^+tnI^SCRBS=c8%q>xUc#5=NFL@ zLABGpi}D3Qh#QOYb~zT3%j77c91Y%u=Ux6-BZkI%VYd*YXdR^YIc~Tm4i#lLD}=~F zgHKE?-(J{SZac_>1-M}W^*T;ivMy0<61NSPM4bbFLz(nM;Ut1$O*J(LNIr3@(Vj|) zziKhv{Ng|M)m^ZJqfQ0%1hdFU+N62O&y5u`i$T!J{OQ zXlKs2zoLwfk11#(g{gfHGGu0vm7|gcr4aW1^3-6KSi@z(Kk(lxv5Ambpgsta7&OD3 zuj5LvNekPbV5zT)MV{1JeGRNq@SOYHLhC9DOUGJhQU^GASrZh2G6h2yhaht2spD$+1*lV5(44xyyU4Um?eZb*(*#@uV0_q z#erTgOnKS1uCDs5y;tsOxgdsdDTpi8+Rhh2cV1H0mmqVkoDuiH4ju zDM^lDbBN8UVHR>ejPETC(UXez)}aYK;X(6k-7ct`~}pa!WAu!Q~hYK3O9M@b23L z4#nG$Fu{OnfDgz2!3(!U`}rf+-@vNfEduWo`N)oJUl2IC_l-cJlyD2m%N#@gI3Hbq zY1|GEr6W?2EK$3!)~?+Z1M`IqlLRTCT#HI>Lp?wWZ}6{)_cAvzh$08hre$}kmj`~F zxAtW-RQ0uxpbBXAoaH}ifArv|r=fH(NKpZz3J`SY2Lc;V6)T{Lh@hSd@Vir`zwIYy zClXh?(I0g*QyB2oT$_=mUw#H-N;uO9L6(Q($wu27BPLr({r`BFQe&n!&fWV?vB8fM zb^p*CE%s5yfZ#Hlu5pGkc7{ISco%=pm5^o!#!84D&hEYFI#@Jbv$`sd@Fim+>xX?u ztpqvc<~Fs{^e|Tm$R<^ixy-o$II7CH956My#w020sk=7!|$jhNZtUT3f{ii+R(FAc_b|!xG^D5KhPQ z*-F9{Qt!FKe@z0+H`#zm3EkjX#JHE~r1xdQ2vV!rQGE@>R67hi#^B5c}3z;q<}?Iwba)uKd?fD_@G)n{i7GVSHF0byT8P*R2VX^&mcAQjwXbICDoj2#{;wsXq4% z^Rf?K_rCRlkAq13SfAQL)ip!JRjC}gmh>=}1$yH*0zlv~B9{>gvn7%%RHC0h*X~y0 zLD0S@`w8@m_ztk#@+dkSd}bTvMJ)uj4#CQbi8*o94Auc$4gnI`qzi&p1M4}S4lH@o zgAo_8R?~SI!aGu>NXjVDu=_VD^!c+am9gzqFjTu1(j|j53X`(jPB9$YP>DtRK?2?# zG^B?~SxamMYo^-E0Z?4o?=SD685I+9-XFS@y@Y|Cj?Apy>+_4`lS;AN{Nl96zR1}Z z`IS~xfUa=2P4@7`*A!vWAmBwtL9g9Hvfl>>i6vV`O6KHND}s+#g$ID3G(^}0!d)H| zCogbO9PxTVDe37%jHpYPIw+|Sxd8dA8w)h8Vn~h=|6Ex+rKzzqg-MmO6T-ihv>X1M zAG-ci)3cULANri%D78bnmt= z^k<*4K-Q?IbS^Q?MZy*10jOSl-JUbex9s*OKB(wq0-omFi+wAjzzp$CnR^jbLr0_O zjW=GBwb%;JHNG~TH0Mw23iUmU78NE=T$--@Xk_P6nle_-s9cZ%vNVX8A++LI=7Uy0 zi{aL+qpZi<{TB8G+D^I9lDNF0u*XtX{29NR+t(9eWzg!notm=Se0tpPw_Rm{09SH$}*l~9`Q4yL)u(ODpuaL%@# zh~gFYHbbE7%vO<5pALu+JqyCzJzgO)ofB!FL#Uq}mIH+1ce#Bwu5`N}nEC6(45bIC=@@k}6l2V?uTN<{pK;_;+S?y!hkgHX@gj|}76iblLu zrr41?7QxTgH}nLYdA@7cCgYag2)a>%^fBG9;1+qDVW&&oCFIZ*YP*_z)R=>SM0y0T zDdOUp6`q5Hq#-s&s(zR$61<{rwdE?Mz;J~JOBe|EQuis?IAGkYT|o*x_eC-z1Vw9( zww0`z)e3L&y52qWg`CX2hUW^~*rLC?PrtHcm)lV^(-5P$iC#5tr+{ikurT%pP(MPwg>#_UXfB77+x?J~bP@_Qd zT%6M_U4fI!&PcUB_60nL=KwK$ns;@O3EYO(s zr8)Qk0oC={OF75TSmss)%~Wz*GCH)gFq@Ko7-gf*E1hhi z{IUJvetEF`&!Rf^a`|oH!wPTKa(avPlWMVDhEbiBZEw=&{8Dwh?P05l8Z&(xV=Z0$ zYRvup{QC9Ur;e5UEtgQYEMPQBdb@19Ocn za&nkvcR$u3FxDmfrl{J@H9oTfpPu010bP+b+sBOpHP+Hb<(p?JXC;^Cgd`RWwZ~O8 zC^Pp5Ete-3Kd;3S|8i;F11TTbi{f~wSfuc}R)Sk*fe}h3<=DlS@4dBXf!n}r&o}pU zu z^YHOH+Z%SFMMIDO;~@PqY-&T}-p>&IiO1WiIqaJWk6}7idA>vW$^o12=7A7W1)9o2 z0i_g1+)JA2%5o~ebq0?009(@CY?Iigs_jUNpBMVn?nB!n4NrFGpR{VO{^K~H6i@Zr zkm@V3lS^9b)MkB+?8lv1!}GHaL0a37etvt4W<2qi^l_&})&~4*e=@Co&r%MQ00pN| zKUnsYq>iZ6tMs$IZ)Om-YulPZ#=9x|<~=%|JbwjN(Vac9sty4v2aR<$>pwy6`?0|~ zol0xnI|H`pZfx!m6UTrNo@bDjaU1*Zg3uzCTe+vYbHHuQG|$myS#KPO zRU@R2uV8oLBLegq;p&T=L+0K^>gd}BZRvSM3I(+mpw~xjM{mh-^}u@kNdu zw_4^o7acRdJ7zTh^S5|e5(fxLoU1c#+P$3esK1*xk$zxv-dIfabvgmShwE(A%>pOq5O2>Mc}Lhruc5XR)|501n>?P|jPsH#v)2 zgIc6rr_6#%@;xuUizV63M4rTRkkQ69BgE6kSg52fxyY@f1T!ThMc3NLozux%laDcw zCCw}`ICYc+%9WQV{`O;(%GtfJ5C>zdCSJZ@aB4R9--`DK8+=*o7k-YDfB63}(w@y1 z^{HizH3eDv3w+(_@Thzha=tx8HPxSPB!doA9wS^86=IctIaB*QNB((w**DR!$HY1za-_f8g6n%gj$WN-fZ z-#>JALfg7_>*kf_uoMl;Nn9~OvTIXa)a4TkDy@raRI!+dkXR0Y^e`Ky=$FrmY!EA& z63m=q7UmBTX)>-dg@*642KE-Yf4k;bF#_f1sH1T0RM{c1DhRj~PAG;Jex*Z}znWaH zlW`Ex{!?WjWa~2Y`?X})ghF+ijoOu|{5#1&f)n4@fR-n&bgI;Fto~|MG%oZ2^Yk8p z_V1Y;>5$}uUsC|Ltp}>(oa4!i7pZY(9=S1XHO>3D!E<{_ZIW3>-hma}2n@J-zgg`N zvnBy%1p~Oe^*;}ChkmbG%5)9Rr38@3DRx6`5f719S>OKK+4h&r7M+17or+e}4SU7! z@O;33g)+jyRoL>Ju^8@v?nf5$c<{w^@C(Ffc@?B|i=BBoko>w(LU5>R_>%9Ry!h%; z{KoJP1jkWt?%B1eE41b@&5;$ C{-s&~ diff --git a/docs/style/coding/CODING_STYLE_GUIDE.adoc b/docs/style/coding/CODING_STYLE_GUIDE.adoc deleted file mode 100644 index d6436523d6..0000000000 --- a/docs/style/coding/CODING_STYLE_GUIDE.adoc +++ /dev/null @@ -1,721 +0,0 @@ -[.text-center] -= Project Connected Home over IP Software -:listing-caption: *Listing* -:toc: macro -:toclevels: 7 -:sectnumlevels: 7 -:sectanchors: -:sectlinks: - -:plusplus: ++ - -:sectnums!: - -== Best Practices, Coding Conventions, and Style - -[.text-center] -_Revision 5_ + -_2020-09-22_ - -[.text-center] -*Status:* [red]*Approved* / [red]*Active* - -toc::[] - -== Typographic and Syntactic Conventions - -The following syntactic conventions are used throughout this document: - -_shall_:: - -is used to indicate a mandatory rule or guideline that must be adhered -to without exception to claim compliance with this specification. - -_should_:: - -is used to indicate a rule or guideline that serves as a strong -preference to suggested practice and is to be followed in the absence of -a compelling reason to do otherwise. - -_may_:: - -is used to indicate a rule or guideline that serves as a reference to -suggested practice. - -== Introduction - -There are likely as many unique combinations of software engineering and -development standards, conventions, and practices as there organizations -that do such work. This document pulls together those that Project -Connected Home over IP believes best for our organization, its efforts, -and products that consume those efforts, with a particular emphasis on -embedded systems with C or C{plusplus} language development and runtime -environments. - -This document and requirements should be considered canonical for all -Project Connected Home over IP shared infrastructure software, including -both RTOS-based and non-RTOS-based projects on both tightly- and -loosely-constrained system platforms. - -The document is broadly categorized at the highest level into: - -* Best Practices and Conventions -* Format and Style - -And, within conventions, further sub-categorized into those that apply -to: - -* Tightly-constrained -* Loosely-constrained - -system platforms. Applicability to tightly-constrained systems also -generally applies to shared infrastructure software that is used on both -tightly- and loosely-constrained systems. - -link:#id.jzphr1iiku89[Figure 1 below] attempts to illustrate both -qualitative and quantitative applicability of these guidelines to -Project Connected Home over IP software. - -Generally, product-specific applications have the greatest flexibility -and latitude in applying these guidelines to their software. Whereas, -shared infrastructure bears the least flexibility and bears the greatest -adherence to these guidelines. - -image:CODING_STYLE_GUIDE-figure1.png[Figure 1. Graphical summary of the -qualitative and quantitative applicability to Project CHIP software.] - -[[id.jzphr1iiku89]] - -[.text-center] -*Figure 1.* Graphical summary of the qualitative and quantitative -applicability to Project CHIP software. - -:sectnums: - -== Standards - -Project CHIP embedded software development adopts the minimum C and C{plusplus} -standards listed in Table 2.1 below. - -[[t.4d8bfeef046f29261fc72f1a903d6d10a909957a]][[t.2]] - -[cols=3,options="header"] -|=== -|Language |Minimum Standard |Aliases - -|C|ISO9899:1999|ISO C99, C99 -|C{plusplus}|ISO14882:2014|ISO C{plusplus}14, C{plusplus}14 -|=== -[.text-center] -*Table 2.1.* C and C{plusplus} language minimum standards adopted by Project CHIP -software. - -Product-specific software may elect to use later standards to the extent -their software is not broadly shared inside or outside Project CHIP. - -=== C - -Project CHIP embedded software development uses and enforces the -ISO9899:1999 (aka ISO C99, C99) C language standard as the minimum. - -Wherever possible, particularly in non-product-specific, -shared-infrastructure software, toolchain-specific (e.g GCC/GNU) -extensions or the use of later standards shall be avoided or shall be -leveraged through toolchain-compatibility preprocessor macros. - -==== Motivation and Rationale - -At the time of this writing, the C99 standard has been out for over 20 -years. Project CHIP and both the new and contributed source code that -comprise it have only existed for the last seven to eight of those -20-plus years. - -This is beyond more than adequate time for this standard to be pervasive -throughout any toolchain vendor’s C compiler and saves team members from -worrying about ISO9899:1990 (aka ISO C90, C90) portability issues that -have long-since been solved by C99. - -=== C{plusplus} - -Project CHIP embedded software development uses the ISO14882:2014 (aka -ISO C{plusplus}14) language standard as a baseline for source code -compatibility. Conformance with other standards, for example, ISO14882:1998 -(aka ISO C{plusplus}98), may be additionally required in cases where wider -portability is necessary, but in all cases, ISO C{plusplus}14 is the baseline -requirement. - -Wherever possible, particularly in non-product-specific, -shared-infrastructure software, toolchain-specific (e.g GCC/GNU) -extensions or the use of later standards shall be avoided or shall be -leveraged through toolchain-compatibility preprocessor macros. - -==== Motivation and Rationale - -CHIP strives to use the latest C++ functionality as long as existing compilers -support such standards. - -C{plusplus}14 is considered pervasive enough to be used. As compilers start -supporting standards such as C{plusplus}17, C{plusplus}20 and beyond, -CHIP may follow suit. - -== Conventions and Best Practices - -=== Common - -The following sections summarize those best practices that are -independent of particular nuances of either the C or C{plusplus} languages. - -==== When in Rome - -The most important convention and practice in the Project CHIP embedded -software is "_When in Rome..._", per the quote below. - -[quote, St. Ambrose] -____ -If you should be in Rome, live in the Roman manner; if you should be -elsewhere, live as they do there. -____ - -===== Motivation and Rationale - -At this stage in the work group’s and the team’s life cycle, it is rare -the project or subsystem that is entirely new and built from scratch. -More often than not, development will involve extending, enhancing, and -fixing existing code in existing projects. - -When in this situation, it is mandatory you observe how things are done -in this context and do the best that you can to follow the prevailing -conventions present. Not doing so can lead to readability and -maintenance problems down the line and will likely earn you the -disapprobation of the code’s _owner_ or other team members. - -Your extensions or fixes to existing code should be *indistinguishable*, -stylistically, from the original code such that the only way to -ascertain ownership and responsibility is to use the source code control -system’s change attribution (aka _blame_) feature. - -If you find the conventions so foreign or otherwise confusing, it may be -best to let whoever owns the file make the necessary changes or seek the -counsel of others in the group to find out what the right thing to do -is. Never just start changing code wholesale for personal reasons -without consulting others first. - -==== Language-independent - -===== Commenting Out or Disabling Code - -Unused code shall not be disabled by commenting it out with C- or -C{plusplus}-style comments or with preprocessor `#if 0 ... #endif` semantics. - -====== Motivation and Rationale - -Code should either be actively maintained and "in" the source base for a -purpose or removed entirely. Code that is disabled in this way is -generally sloppy and does not convey a sense of certainty and direction -in the code. - -Anyone who is interested in the history of a particular source code file -should use the source code control system to browse it. - -Code that is debug- or test-only should be moved to a conditionally -compiled test source file or conditionalized with an appropriate -`WITH_DEBUG`, `WANT_DEBUG`, `WITH_TESTS`, `WANT_TESTS`, or some similar such -preprocessor mnemonic that can be asserted from the build system. - -===== Use C _stdint.h_ or C{plusplus} _cstdint_ for Plain Old Data Types - -Standard, scalar data types defined in _stdint.h_ \(C) or _cstdint_ (C{plusplus}) -should be used for basic signed and unsigned integer types, especially -when size and serialization to non-volatile storage or across a network -is concerned. - -Examples of these are: `uint8_t`, `int8_t`, etc. - -====== Motivation and Rationale - -These types have been effectively standardized since C99 and should be -available on every platform and provide more neutral portability than -OS-specific types such as `u8`, `UInt8`, etc. Moreover, because these are -pervasive, you do not need to spend any time and energy as a developer -and engineer creating more such types on your own—the compiler vendors -have already done the hard work for you. - -Additionally, using traditional scalar types such as `char`, `int`, `short`, or -`long` have portability issues where data width is concerned because these -types are either signed- or sized-differently on different processor -architectures and and ABIs for those architectures. For example, a char is signed -on some architectures and unsigned on others and a long is 32-bits on some -architectures and 64-bits on others. - -==== Language-dependent - -===== C{plusplus} - -====== Avoid `using namespace` Statements in Headers - -By doing this, you are effectively forcing every other module that -includes the header to also be using the namespace. This causes -namespace pollution and generally defeats the purposes of namespaces. -Fully-qualified symbols should be used instead. - -=== Tightly-constrained Systems and Shared Infrastructure - -Applicability to tightly-constrained systems also generally applies to -shared infrastructure software that is used on both tightly- and -loosely-constrained systems. - -==== Avoid Heap-based Resource Allocation - -Heap-based resource allocation should be avoided. - -===== Motivation and Rationale - -As emphasized throughout this document, the software produced by Project -CHIP is consumed both inside and outside Project CHIP, across a variety -of platforms. The capabilities of these platforms are broad, spanning -soft real-time, deeply-embedded systems based on RTOSes that -may cover life safety and/or physical security applications to richer, -softly-embedded systems based on non-RTOS platforms such as Darwin or -Linux. While the latter are apt to have fully-functional heaps, the -former explicitly may not. - -Consequently, when planning new or extending existing Project CHIP code, -consider the platforms to which the code is targeted. If the platforms -include those deeply-embedded platforms absent functioning heaps, then -heap-based resource allocation is absolutely forbidden. If not, -consideration should be made to the cost / benefit trade-offs of -heap-based allocation and, if possible, it should be avoided using one -of the recommended techniques below. - -===== Alternatives - -In either case, recommended resource allocation alternatives are: - -* In Place Allocation and Initialization -* Pool-based Allocators -* Platform-defined and -assigned Allocators - -The interfaces in https://github.com/project-chip/connectedhomeip/blob/master/src/lib/support/CHIPMem.h[_src/lib/support/CHIPMem.h_] provide support for -the latter two alternatives. - -====== Use In Place Allocation and Initialization - -Regardless of whether the source code and runtime are C or C{plusplus}, the -first step is creating storage for the object being allocated and -initialized. For simple -https://en.wikipedia.org/wiki/Passive_data_structure[plain-old-data -(POD)] data structures, this can be done by just allocating the -structure at an appropriate scope. Alternatively, _raw_ storage can be -allocated and then cast. However, great care must be taken with the -latter approach to ensure that natural machine alignments and language -strict-aliasing rules are observed. With the simple data structure -declaration, the compiler does this on your behalf. With the raw -approach, you must do this. - -Once the storage has been allocated, then use symmetric initializers and -deinitializers such as those, for example, for `pthread_attr_t`. An -example is shown in the listing below. - -[source,C,caption='',title='{listing-caption} *{counter:refnum}*. Using in place allocation and initialization in C or C{plusplus}.'] ----- -#include -#include - -... - -// Preprocessor Definitions - -// Allocate the structure using "raw" storage. - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#include - -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - typename std::aligned_storage::type name; - -#else -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))] - -#endif // defined(__cplusplus) && (__cplusplus >= 201103L) - -// Forward Declarations - -extern void * foobar_entry(void *aArgument); - -// Global Variables - -#if USE_STRUCT_STORAGE -// Allocate the structure directly. -static pthread_attr_t sThreadAttributes; - -#elif USE_RAW_STORAGE -static chipDEFINE_ALIGNED_VAR(sThreadAttributes, sizeof (pthread_attr_t), uint64_t); - -#endif // USE_STRUCT_STORAGE - -int foobar() -{ - int retval; - int status; - pthread_t thread; - pthread_attr_t * attrs = (pthread_attr_t *)&sThreadAttributes; - - // Now "construct" or initialize the storage. - retval = pthread_attr_init(attrs); - - if (retval == 0) - { - retval = pthread_create(&thread, attrs, foobar_entry, NULL); - - if (retval == 0) - { - status = pthread_join(thread, NULL); - - if (status != 0) - { - retval = status; - } - - status = pthread_attr_destroy(attrs); - - if (status != 0) - { - retval = status; - } - } - } - - return (retval); -} ----- - -For non-scalar types and objects such as C{plusplus} classes, this gets slightly -trickier since C{plusplus} constructors and destructors must be accounted for -and invoked. Fortunately, C{plusplus} has placement new which handles this. -The listing below modifies the listing above using C{plusplus} placement new -to ensure the class is properly constructed before initialization and -destructed after deinitialization. - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using C{plusplus} placement new for in place allocation and initialization.'] ----- -#include - -#include -#include - -... - -// Preprocessor Definitions - -// Allocate the structure using "raw" storage. - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#include - -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - typename std::aligned_storage::type name; - -#else -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))] - -#endif // defined(__cplusplus) && (__cplusplus >= 201103L) - -// Type Declarations - -class ThreadAttributes -{ -public: - ThreadAttributes() {}; - ~ThreadAttributes() {}; - - operator pthread_attr_t *() { return &mAttributes; } - -private: - pthread_attr_t mAttributes; -}; - -// Forward Declarations - -extern void * foobar_entry(void *aArgument); - -// Global Variables - -static chipDEFINE_ALIGNED_VAR(sThreadAttributes, sizeof (ThreadAttributes), uint64_t); - -int foobar() -{ - int retval = -1; - int status; - pthread_t thread; - ThreadAttributes * ta; - pthread_attr_t * attrs; - - ta = new (&sThreadAttributes) ThreadAttributes; - - if (ta != NULL) - { - attrs = static_cast(*ta); - - // Now "construct" or initialize the storage. - retval = pthread_attr_init(attrs); - - if (retval == 0) - { - retval = pthread_create(&thread, attrs, foobar_entry, NULL); - - if (retval == 0) - { - status = pthread_join(thread, NULL); - - if (status != 0) - { - retval = status; - } - - status = pthread_attr_destroy(attrs); - - if (status != 0) - { - retval = status; - } - } - } - - ta->~ThreadAttributes(); - } - - return retval; -} ----- - -====== Use Pool-based Allocators - -In place allocation allows the successful allocation, initialization, -deinitialization, and deallocation of a single object allocated from -preallocated storage. However, if the desire exists for a fixed, -configurable pool of objects where 0 to `n` of such objects can be -allocated at any one time, a pool allocator for that specific object -type must be created. - -As shown in the listing below, a pool allocator for a `Foo` class of -`CHIP_FOO_COUNT` objects is effected, assuming the existence of another -helper class, StaticAllocatorBitmap, which uses a bitmap to track the -storage of objects from a static array of storage. - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using pool-based allocators.'] ----- - -#include - -// Preprocessor Definitions - -// Allocate the structure using "raw" storage. - -#if defined(__cplusplus) && (__cplusplus >= 201103L) -#include - -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - typename std::aligned_storage::type name; - -#else -#define chipDEFINE_ALIGNED_VAR(name, size, align_type) \ - align_type name[(((size) + (sizeof (align_type) - 1)) / sizeof (align_type))] - -#endif // defined(__cplusplus) && (__cplusplus >= 201103L) - -// Type Definitions - -class Foo -{ -public: - Foo(); - Foo(const Foo &inFoo); - ~Foo(); -}; - -// Global Variables - -static chipDEFINE_ALIGNED_VAR(sFooAllocatorBuffer, sizeof (StaticAllocatorBitmap), uint32_t); -static StaticAllocatorBitmap *sFooAllocator; - -static void CreateFooAllocator(void *inStorage, - const StaticAllocatorBitmap::size_type &inStorageSize, - const StaticAllocatorBitmap::size_type &inElementCount, - StaticAllocatorBitmap::InitializeFunction inInitialize, - StaticAllocatorBitmap::DestroyFunction inDestroy) -{ - sFooAllocator = new (sFooAllocatorBuffer) - StaticAllocatorBitmap(inStorage, - inStorageSize, - inElementCount, - inInitialize, - inDestroy); -} - -static StaticAllocatorBitmap &GetFooAllocator() -{ - return *sFooAllocator; -} - -static void *FooInitialize(AllocatorBase &inAllocator, void *inObject) -{ - memset(inObject, 0, sizeof(Foo)); - - return inObject; -} - -static void FooDestroy(AllocatorBase &inAllocator, void *inObject) -{ - return; -} - -int Init() -{ - static const size_t sFooCount = CHIP_FOO_COUNT; - static chipAllocatorStaticBitmapStorageDefine(sFooStorage, Foo, sFooCount, uint32_t, sizeof (void *)); - int retval = 0; - - CreateFooAllocator(sFooStorage, - sizeof (sFooStorage), - sFooCount, - FooInitialize, - FooDestroy); - - return retval; -} - -Foo * FooAllocate() -{ - Foo *foo; - - foo = static_cast(GetFooAllocator().allocate()); - - return foo; -} - -void FooDeallocate(Foo *inFoo) -{ - GetFooAllocator().deallocate(inFoo); -} ----- - -====== Use Platform-defined and -assigned Allocators - -This is a variation on both in place allocation and pool-based -allocation in that it completely delegates resource allocation to the -system integrator and the platform on which the particular software -subsystem is running. - -The advantage of this approach is that it allows the platform to decide -how resource allocation will be handled and allows the package to scale -independently of platform resource allocation. - -The package may define default implementations for a few types of -platform allocation strategies, such as heap-based allocators and -pool-based allocators. - -There are a range of granularities for achieving this type of -delegation, depending on the desired size of the API surface, as shown -in the listings below. - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using a common allocator method pattern with unique allocators per object, accessed from a unique singleton access per allocator.'] ----- - -chipPlatformInitFooAllocator(); -chipPlatformInitBarAllocator(); -… -foo = chipPlatformGetFooAllocator().allocate(); -… -chipPlatformGetFooAllocator().deallocate(foo); -… -bar = chipPlatformGetBarAllocator().allocate(); -… -chipPlatformGetBarAllocator().deallocate(bar); ----- - -[source,C++,caption='',title='{listing-caption} *{counter:refnum}*. Using a common allocator method pattern with unique allocators per object, accessed from a common singleton access with type per allocator.'] ----- -chipPlatformInitAllocator(CHIP_FOO_T); -chipPlatformInitAllocator(CHIP_BAR_T); -… -foo = chipPlatformGetAllocator(CHIP_FOO_T).allocate(); -… -chipPlatformGetAllocator(CHIP_FOO_T).deallocate(foo); -… -bar = chipPlatformGetAllocator(CHIP_BAR_T).allocate(); -… -chipPlatformGetAllocator(CHIP_BAR_T).deallocate(bar); ----- - -[source,C,caption='',title='{listing-caption} *{counter:refnum}*. Using unique allocators per object.'] ----- -chipPlatformInitFooAllocator(); -chipPlatformInitBarAllocator(); -… -foo = chipPlatformFooAllocate(); -… -chipPlatformFooDeallocate(foo); -… -bar = chipPlatformBarAllocate(); -… -chipPlatformBarDeallocate(bar); ----- - -[source,C,caption='',title='{listing-caption} *{counter:refnum}*. Using a common allocator pattern with unique allocators per object, accessed from a common interface with type per allocator.'] ----- - -chipPlatformInitAllocator(CHIP_FOO_T); -chipPlatformInitAllocator(CHIP_BAR_T); -… -foo = chipPlatformAllocate(CHIP_FOO_T); -… -chipPlatformDeallocate(CHIP_FOO_T, foo); -… -bar = chipPlatformAllocate(CHIP_BAR_T); -… -chipPlatformBarDeallocate(CHIP_BAR_T, bar); ----- - -:sectnums!: - -== Recommended Reading - -While the following references and reading are not part of the formal -best practices, coding conventions, and style cannon, they are -informative and useful guides for improving the style and quality of the -code you write: - -. Jet Propulsion Laboratory. -http://lars-lab.jpl.nasa.gov/JPL_Coding_Standard_C.pdf[JPL -Institutional Coding Standard for the C Programming Language.] Version -1.0. March 3, 2009. -. Jet Propulsion Laboratory. -http://pixelscommander.com/wp-content/uploads/2014/12/P10.pdf[The -Power of Ten – Rules for Developing Safety Critical Code]. December -2014. -. Meyers, Scott. Effective C{plusplus}: 55 Specific Ways to Improve Your -Programs and Designs. Third Edition. 2005. -. Meyers, Scott. More Effective C{plusplus}: 35 New Ways to Improve Your -Programs and Designs. 1996. -. Meyers. Scott. https://www.artima.com/shop/effective_cpp_in_an_embedded_environment[Effective C{plusplus} in an Embedded Environment]. 2015. -. Motor Industry Software Reliability Association. Guidelines for the -Use of the C Language in Critical Systems. March 2013. -. Motor Industry Software Reliability Association. Guidelines for the -Use of the C{plusplus} Language in Critical Systems. June 2008. - -== Revision History - -[cols="^1,^1,<2,<3",options="header"] -|=== -|Revision |Date |Modified By |Description -|5 |2020-09-22 |Grant Erickson |Added Tightly-constrained Systems and Shared Infrastructure > Avoid Heap-based Resource Allocation -|4 |2020-09-15 |Grant Erickson |Added Common > Language-dependent > Avoid `using namespace` Statements in Headers -|3 |2020-09-01 |Grant Erickson |Added Common > Language-independent > Use C _stdint.h_ or C{plusplus} _cstdint_ for Plain Old Data Types -|2 |2020-07-09 |Grant Erickson |Added Common > Language-independent > Commenting Out or Disabling Code -|1 |2020-07-08 |Grant Erickson |Initial revision. -|=== - -[.text-center] -_Project Connect Home over IP Public Information_ From c56d0f0ecf1137a2cd96c8b2a11bebacbc18f58d Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Mon, 18 Nov 2024 13:07:23 -0800 Subject: [PATCH 037/219] [Fabric-Sync] Set remote bridge after reverse pair the bridge device (#36509) * Set remote bridge after reverse pair the bridge device * Address review comment --- examples/fabric-sync/admin/DeviceManager.cpp | 18 +++++++++---- examples/fabric-sync/admin/DeviceManager.h | 5 ++++ examples/fabric-sync/admin/FabricAdmin.cpp | 27 +++++++++++++++++-- examples/fabric-sync/admin/FabricAdmin.h | 7 +++-- examples/fabric-sync/admin/PairingManager.cpp | 12 ++++----- .../fabric-sync/shell/AddBridgeCommand.cpp | 1 + 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index f9685295e4..00e6988a2c 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -72,11 +72,7 @@ void DeviceManager::UpdateLastUsedNodeId(NodeId nodeId) void DeviceManager::SetRemoteBridgeNodeId(chip::NodeId nodeId) { mRemoteBridgeNodeId = nodeId; - - if (mRemoteBridgeNodeId != kUndefinedNodeId) - { - mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); - } + ChipLogProgress(NotSpecified, "Set remote bridge NodeId:" ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); } void DeviceManager::AddSyncedDevice(const SyncedDevice & device) @@ -131,6 +127,18 @@ void DeviceManager::RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId) ChipLogValueX64(device->GetNodeId()), device->GetEndpointId()); } +void DeviceManager::InitCommissionerControl() +{ + if (mRemoteBridgeNodeId != kUndefinedNodeId) + { + mCommissionerControl.Init(PairingManager::Instance().CurrentCommissioner(), mRemoteBridgeNodeId, kAggregatorEndpointId); + } + else + { + ChipLogError(NotSpecified, "Failed to initialize the Commissioner Control delegate"); + } +} + void DeviceManager::OpenLocalBridgeCommissioningWindow(uint32_t iterations, uint16_t commissioningTimeoutSec, uint16_t discriminator, const ByteSpan & salt, const ByteSpan & verifier) { diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index 9afb1eec7d..d2f829ec40 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -76,6 +76,11 @@ class DeviceManager void RemoveSyncedDevice(chip::ScopedNodeId scopedNodeId); + /** + * @brief Initializes the CommissionerControl for fabric sync setup process. + */ + void InitCommissionerControl(); + /** * @brief Determines whether a given nodeId corresponds to the remote bridge device. * diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 4e170ce78d..ed2126d34e 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -86,13 +86,14 @@ FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParam if (err == CHIP_NO_ERROR) { - NodeId nodeId = DeviceManager::Instance().GetNextAvailableNodeId(); + mNodeId = DeviceManager::Instance().GetNextAvailableNodeId(); // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); - DeviceManager::Instance().PairRemoteDevice(nodeId, code.c_str()); + PairingManager::Instance().SetPairingDelegate(this); + DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str()); } else { @@ -115,6 +116,28 @@ CHIP_ERROR FabricAdmin::KeepActive(ScopedNodeId scopedNodeId, uint32_t stayActiv return CHIP_NO_ERROR; } +void FabricAdmin::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mNodeId != deviceId) + { + ChipLogError(NotSpecified, "Tried to pair a non-bridge device (0x:" ChipLogFormatX64 ") with result: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + return; + } + + if (err == CHIP_NO_ERROR) + { + DeviceManager::Instance().SetRemoteBridgeNodeId(deviceId); + } + else + { + ChipLogError(NotSpecified, "Failed to pair bridge device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + mNodeId = kUndefinedNodeId; +} + void FabricAdmin::ScheduleSendingKeepActiveOnCheckIn(ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) { // Accessing mPendingCheckIn should only be done while holding ChipStackLock diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h index bec98dc414..f2634156ee 100644 --- a/examples/fabric-sync/admin/FabricAdmin.h +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -37,7 +37,7 @@ struct ScopedNodeIdHasher } }; -class FabricAdmin final : public bridge::FabricAdminDelegate +class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDelegate { public: static FabricAdmin & Instance(); @@ -51,6 +51,8 @@ class FabricAdmin final : public bridge::FabricAdminDelegate CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) override; + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; + void ScheduleSendingKeepActiveOnCheckIn(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs); private: @@ -88,7 +90,8 @@ class FabricAdmin final : public bridge::FabricAdminDelegate static FabricAdmin sInstance; - bool mInitialized = false; + bool mInitialized = false; + chip::NodeId mNodeId = chip::kUndefinedNodeId; void Init() { mInitialized = true; } }; diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index 954680fe17..eeb8ad09ff 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -281,6 +281,12 @@ void PairingManager::OnPairingDeleted(CHIP_ERROR err) void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { + if (mPairingDelegate) + { + mPairingDelegate->OnCommissioningComplete(nodeId, err); + SetPairingDelegate(nullptr); + } + if (err == CHIP_NO_ERROR) { // print to console @@ -294,12 +300,6 @@ void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) { ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err)); } - - if (mPairingDelegate) - { - mPairingDelegate->OnCommissioningComplete(nodeId, err); - SetPairingDelegate(nullptr); - } } void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioningInfo & info) diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index e6b9dd0603..e06f8882d2 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -55,6 +55,7 @@ void AddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) admin::DeviceManager::Instance().UpdateLastUsedNodeId(mBridgeNodeId); admin::DeviceManager::Instance().SubscribeRemoteFabricBridge(); + admin::DeviceManager::Instance().InitCommissionerControl(); // After successful commissioning of the Commissionee, initiate Reverse Commissioning // via the Commissioner Control Cluster. However, we must first verify that the From d8ededa4ada21149867032d96fab50c76e52ec9e Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Mon, 18 Nov 2024 16:09:41 -0800 Subject: [PATCH 038/219] Update the readme of fabric-sync app based on the latest update (#36540) * Update the readme of fabric-sync app based on the latest update * Restyled by prettier-markdown * Remove extra comma --------- Co-authored-by: Restyled.io --- examples/fabric-admin/rpc/RpcServer.cpp | 1 - examples/fabric-sync/README.md | 69 +++++++++++++++++++++---- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index f59a2729db..06f7d8217c 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -174,7 +174,6 @@ class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate if (error == CHIP_NO_ERROR) { mNodeId = DeviceManager::Instance().GetNextAvailableNodeId(); - ; // After responding with RequestCommissioningApproval to the node where the client initiated the // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. diff --git a/examples/fabric-sync/README.md b/examples/fabric-sync/README.md index 0fd4735c74..fd943e461f 100644 --- a/examples/fabric-sync/README.md +++ b/examples/fabric-sync/README.md @@ -80,30 +80,30 @@ defined: ## Building - ### For Linux host example: +- For Linux host example: - ``` + ```sh source scripts/activate.sh ./scripts/build/build_examples.py --target linux-x64-fabric-sync-no-ble build ``` - ### For Raspberry Pi 4 example: +- For Raspberry Pi 4 example: Pull Docker Images - ``` + ```sh docker pull ghcr.io/project-chip/chip-build-crosscompile:90 ``` Run docker - ``` + ```sh docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash ``` Build - ``` + ```sh cd /var/connectedhomeip git config --global --add safe.directory /var/connectedhomeip @@ -116,7 +116,7 @@ defined: Transfer the fabric-bridge-app binary to a Raspberry Pi - ``` + ```sh scp ./fabric-sync ubuntu@xxx.xxx.xxx.xxx:/home/ubuntu ``` @@ -126,9 +126,60 @@ defined: Follow [Building](#building) section of this document. -- Run Linux Fabric Sync Example App +- Run Linux Fabric Sync Example App on two Linux machine E1 and E2 ```sh + sudo rm -rf /tmp/chip_* cd ~/connectedhomeip/ - sudo out/debug/fabric-sync + out/debug/fabric-sync + ``` + +- Initiate the FS Setup Process from E1 to E2 + + ```sh + > app add-bridge 1 20202021 192.168.86.246 5540 + Done + > New device with Node ID: 0000000000000001 has been successfully added. + A new device has been added on Endpoint: 2. + ``` + +- Verify Reverse Commissioning of the Fabric-Bridge from E1 on E2 + + ```sh + > New device with Node ID: 0000000000000002 has been successfully added. + ``` + +- Pair Light Example to E2 + + Since Fabric-Bridge also functions as a Matter server, running it alongside + the Light Example app on the same machine would cause conflicts. Therefore, + you need to run the Matter Light Example app on a separate physical machine + from the one hosting Fabric-Sync. + + ```sh + > app add-device 3 + ``` + + After the device is successfully added, you will observe the following + message on E2 with the newly assigned Node ID: + + ```sh + > New device with Node ID: 0x3 has been successfully added. + ``` + + Additionally, you should also get notified when a new device is added to E2 + from the E1: + + ```sh + > A new device is added on Endpoint 3. + ``` + +- Synchronize Light Example to E1 + + After the Light Example is successfully paired in E2, we can start to + synchronize the light device to E1 using the new assigned dynamic endpointid + on Ecosystem 2. + + ```sh + > app sync-device ``` From 8fe45964a2fdf881e0dfea99a431f499980c0263 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Tue, 19 Nov 2024 13:26:35 +0200 Subject: [PATCH 039/219] [Telink] Add tl3218x board support & Update builds to docker version 92 (#36409) * [Telink] Add TL3218X sceleton * [Telink] Disable temporarry BLE * [Telink] save ram by change config & revert add retention board * riscv: telink:tl3218x: clean code and fix CI. - fix CI error. - clean code and improve settings. - delete retention setting for TL321X. Signed-off-by: Haiwen Xia * [Telink] Revert add retention board --------- Signed-off-by: Haiwen Xia Co-authored-by: Alex Tsitsiura * riscv: telink:tl3218x: add ble optimize. - add optimize for ble. - low down the ramcost. - revert nvs cache to pass certify. Signed-off-by: Haiwen Xia * [Telink] Add LZMA compression support for TL321x platform Signed-off-by: Jinmiao Yu * [Telink] Use LZMA by default for tl321x * [Telink] CI build tests * Restyled by clang-format * [Telink] Update Config B9X_BLE_ to TL_BLE_ Signed-off-by: Damien Ji * [Telink] update zephyr revision for CI build tests Signed-off-by: Damien Ji * [Telink] update zephyr revision for CI build tests Signed-off-by: Damien Ji * [Telink] Cleanup overlays * [Telink] update zephyr revision for CI build tests Signed-off-by: Damien Ji * [Telink] Increase ISR and CHIP stack sizes to avoid 90%+ usage * [Telink] Update builds to docker version 92 --------- Signed-off-by: Haiwen Xia Signed-off-by: Jinmiao Yu Signed-off-by: Damien Ji Co-authored-by: haiwentelink <125550736+haiwentelink@users.noreply.github.com> Co-authored-by: Haiwen Xia Co-authored-by: Jinmiao Yu Co-authored-by: Restyled.io Co-authored-by: Damien Ji --- .github/workflows/bloat_check.yaml | 2 +- .github/workflows/build.yaml | 10 +-- .github/workflows/chef.yaml | 10 +-- .github/workflows/doxygen.yaml | 2 +- .github/workflows/examples-ameba.yaml | 2 +- .github/workflows/examples-asr.yaml | 2 +- .github/workflows/examples-bouffalolab.yaml | 2 +- .github/workflows/examples-cc13xx_26xx.yaml | 2 +- .github/workflows/examples-cc32xx.yaml | 2 +- .github/workflows/examples-efr32.yaml | 2 +- .github/workflows/examples-esp32.yaml | 4 +- .github/workflows/examples-infineon.yaml | 2 +- .github/workflows/examples-linux-arm.yaml | 2 +- .github/workflows/examples-linux-imx.yaml | 2 +- .../workflows/examples-linux-standalone.yaml | 2 +- .../examples-linux-tv-casting-app.yaml | 2 +- .github/workflows/examples-mw320.yaml | 2 +- .github/workflows/examples-nrfconnect.yaml | 2 +- .github/workflows/examples-nuttx.yaml | 2 +- .github/workflows/examples-nxp.yaml | 4 +- .github/workflows/examples-openiotsdk.yaml | 2 +- .github/workflows/examples-qpg.yaml | 2 +- .github/workflows/examples-stm32.yaml | 2 +- .github/workflows/examples-telink.yaml | 17 ++++- .github/workflows/examples-tizen.yaml | 2 +- .github/workflows/full-android.yaml | 2 +- .github/workflows/fuzzing-build.yaml | 2 +- .github/workflows/java-tests.yaml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/minimal-build.yaml | 4 +- .github/workflows/qemu.yaml | 4 +- .github/workflows/release_artifacts.yaml | 4 +- .github/workflows/smoketest-android.yaml | 2 +- .github/workflows/tests.yaml | 4 +- .github/workflows/unit_integration_test.yaml | 2 +- .github/workflows/zap_regeneration.yaml | 2 +- .github/workflows/zap_templates.yaml | 2 +- config/telink/chip-module/CMakeLists.txt | 2 +- config/telink/chip-module/Kconfig | 3 +- config/telink/chip-module/Kconfig.defaults | 67 ++++++++++++++----- examples/all-clusters-app/ameba/README.md | 4 +- .../all-clusters-minimal-app/ameba/README.md | 4 +- examples/fabric-admin/README.md | 4 +- examples/fabric-bridge-app/linux/README.md | 4 +- examples/fabric-sync/README.md | 4 +- examples/light-switch-app/ameba/README.md | 4 +- examples/lighting-app/ameba/README.md | 4 +- examples/ota-requestor-app/ameba/README.md | 4 +- examples/pigweed-app/ameba/README.md | 4 +- examples/platform/telink/common.cmake | 2 +- .../telink/project_include/OpenThreadConfig.h | 7 +- integrations/cloudbuild/chef.yaml | 8 +-- integrations/cloudbuild/smoke-test.yaml | 14 ++-- scripts/build/build/targets.py | 1 + scripts/build/builders/telink.py | 3 + .../build/testdata/all_targets_linux_x64.txt | 2 +- .../telink/CHIPDevicePlatformConfig.h | 6 ++ src/platform/telink/CHIPPlatformConfig.h | 16 ++++- src/platform/telink/SystemPlatformConfig.h | 9 ++- src/platform/telink/tl3218x.overlay | 61 +++++++++++++++++ src/platform/telink/tl3218x_2m_flash.overlay | 39 +++++++++++ 61 files changed, 288 insertions(+), 105 deletions(-) create mode 100644 src/platform/telink/tl3218x.overlay create mode 100644 src/platform/telink/tl3218x_2m_flash.overlay diff --git a/.github/workflows/bloat_check.yaml b/.github/workflows/bloat_check.yaml index 43a3993eee..465526ea87 100644 --- a/.github/workflows/bloat_check.yaml +++ b/.github/workflows/bloat_check.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 steps: - name: Checkout diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 92acd73ace..4d16657b35 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -43,7 +43,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -139,7 +139,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -308,7 +308,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -371,7 +371,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -490,7 +490,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/chef.yaml b/.github/workflows/chef.yaml index d7360f6cc4..d2298bbca3 100644 --- a/.github/workflows/chef.yaml +++ b/.github/workflows/chef.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 options: --user root steps: @@ -57,7 +57,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:92 options: --user root steps: @@ -78,7 +78,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:90 + image: ghcr.io/project-chip/chip-build-nrf-platform:92 options: --user root steps: @@ -99,7 +99,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:90 + image: ghcr.io/project-chip/chip-build-telink:92 options: --user root steps: @@ -111,7 +111,7 @@ jobs: platform: telink # - name: Update Zephyr to specific revision (for developers purpose) # shell: bash - # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py f762f1a1027284e63e338e6d83deeade62f355b0" + # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 9ab2325bf76bc7bec92a3ff93fad80ec5d3eae7c" - name: CI Examples Telink shell: bash run: | diff --git a/.github/workflows/doxygen.yaml b/.github/workflows/doxygen.yaml index e345ff2a75..4af7b3d8ed 100644 --- a/.github/workflows/doxygen.yaml +++ b/.github/workflows/doxygen.yaml @@ -84,7 +84,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-doxygen:90 + image: ghcr.io/project-chip/chip-build-doxygen:92 if: github.actor != 'restyled-io[bot]' diff --git a/.github/workflows/examples-ameba.yaml b/.github/workflows/examples-ameba.yaml index a4b40a1933..92ee46b49d 100644 --- a/.github/workflows/examples-ameba.yaml +++ b/.github/workflows/examples-ameba.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ameba:90 + image: ghcr.io/project-chip/chip-build-ameba:92 options: --user root steps: diff --git a/.github/workflows/examples-asr.yaml b/.github/workflows/examples-asr.yaml index 143ce3364f..ce4fef94fd 100644 --- a/.github/workflows/examples-asr.yaml +++ b/.github/workflows/examples-asr.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-asr:90 + image: ghcr.io/project-chip/chip-build-asr:92 options: --user root steps: diff --git a/.github/workflows/examples-bouffalolab.yaml b/.github/workflows/examples-bouffalolab.yaml index 2e9cf4a884..ed6e583285 100644 --- a/.github/workflows/examples-bouffalolab.yaml +++ b/.github/workflows/examples-bouffalolab.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-bouffalolab:90 + image: ghcr.io/project-chip/chip-build-bouffalolab:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-cc13xx_26xx.yaml b/.github/workflows/examples-cc13xx_26xx.yaml index 097a7d103e..68f5ecf09f 100644 --- a/.github/workflows/examples-cc13xx_26xx.yaml +++ b/.github/workflows/examples-cc13xx_26xx.yaml @@ -42,7 +42,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ti:90 + image: ghcr.io/project-chip/chip-build-ti:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-cc32xx.yaml b/.github/workflows/examples-cc32xx.yaml index 25afa79903..935c5df723 100644 --- a/.github/workflows/examples-cc32xx.yaml +++ b/.github/workflows/examples-cc32xx.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ti:90 + image: ghcr.io/project-chip/chip-build-ti:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index dd9fb120a3..1b970abf6a 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-efr32:90 + image: ghcr.io/project-chip/chip-build-efr32:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index 9853c0df51..ba90be6082 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -124,7 +124,7 @@ jobs: if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif' container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-infineon.yaml b/.github/workflows/examples-infineon.yaml index 49c2097cd6..165d9015fa 100644 --- a/.github/workflows/examples-infineon.yaml +++ b/.github/workflows/examples-infineon.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-infineon:90 + image: ghcr.io/project-chip/chip-build-infineon:92 env: # TODO: this should probably be part of the dockerfile itself CY_TOOLS_PATHS: /opt/Tools/ModusToolbox/tools_3.2 diff --git a/.github/workflows/examples-linux-arm.yaml b/.github/workflows/examples-linux-arm.yaml index 46c2173530..5815d1d1d3 100644 --- a/.github/workflows/examples-linux-arm.yaml +++ b/.github/workflows/examples-linux-arm.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-crosscompile:90 + image: ghcr.io/project-chip/chip-build-crosscompile:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-imx.yaml b/.github/workflows/examples-linux-imx.yaml index e1d64f7a05..69d832282a 100644 --- a/.github/workflows/examples-linux-imx.yaml +++ b/.github/workflows/examples-linux-imx.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-imx:90 + image: ghcr.io/project-chip/chip-build-imx:92 steps: - name: Checkout diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index 8c483cacd4..5c1fbcbdf6 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-tv-casting-app.yaml b/.github/workflows/examples-linux-tv-casting-app.yaml index 14bfb6fb91..8480509c00 100644 --- a/.github/workflows/examples-linux-tv-casting-app.yaml +++ b/.github/workflows/examples-linux-tv-casting-app.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 steps: - name: Checkout diff --git a/.github/workflows/examples-mw320.yaml b/.github/workflows/examples-mw320.yaml index 077bdbbfb7..65a23f6b1a 100644 --- a/.github/workflows/examples-mw320.yaml +++ b/.github/workflows/examples-mw320.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index 0db5e82e81..bc8fbde4da 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:90 + image: ghcr.io/project-chip/chip-build-nrf-platform:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-nuttx.yaml b/.github/workflows/examples-nuttx.yaml index cccfa44557..e9b214f3e4 100644 --- a/.github/workflows/examples-nuttx.yaml +++ b/.github/workflows/examples-nuttx.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nuttx:90 + image: ghcr.io/project-chip/chip-build-nuttx:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index aa782544d2..9348baa833 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp:90 + image: ghcr.io/project-chip/chip-build-nxp:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -240,7 +240,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp-zephyr:90 + image: ghcr.io/project-chip/chip-build-nxp-zephyr:92 steps: - name: Checkout diff --git a/.github/workflows/examples-openiotsdk.yaml b/.github/workflows/examples-openiotsdk.yaml index 2d59643eeb..4ff65c0c94 100644 --- a/.github/workflows/examples-openiotsdk.yaml +++ b/.github/workflows/examples-openiotsdk.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-openiotsdk:90 + image: ghcr.io/project-chip/chip-build-openiotsdk:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" options: --privileged diff --git a/.github/workflows/examples-qpg.yaml b/.github/workflows/examples-qpg.yaml index 3287b281dc..64f6678818 100644 --- a/.github/workflows/examples-qpg.yaml +++ b/.github/workflows/examples-qpg.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-stm32.yaml b/.github/workflows/examples-stm32.yaml index d10c91a8e8..dad94e5267 100644 --- a/.github/workflows/examples-stm32.yaml +++ b/.github/workflows/examples-stm32.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-telink.yaml b/.github/workflows/examples-telink.yaml index 6c8b9bd521..c24b8f5565 100644 --- a/.github/workflows/examples-telink.yaml +++ b/.github/workflows/examples-telink.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:90 + image: ghcr.io/project-chip/chip-build-telink:92 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -58,7 +58,7 @@ jobs: gh-context: ${{ toJson(github) }} # - name: Update Zephyr to specific revision (for developers purpose) - # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py f762f1a1027284e63e338e6d83deeade62f355b0" + # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 9ab2325bf76bc7bec92a3ff93fad80ec5d3eae7c" - name: Build example Telink (B92 retention) Air Quality Sensor App # Run test for master and s07641069 PRs @@ -167,6 +167,19 @@ jobs: - name: clean out build output (keep tools) run: rm -rf ./out/telink* + - name: Build example Telink (tl321x) Lighting App with OTA (LZMA), Shell, Factory Data + # Run test for master and all PRs + run: | + ./scripts/run_in_build_env.sh \ + "./scripts/build/build_examples.py --target 'telink-tl3218x-light-ota-compress-lzma-shell-factory-data' build" + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + telink tl3218x light-app-ota-compress-lzma-shell-factory-data \ + out/telink-tl3218x-light-ota-compress-lzma-shell-factory-data/zephyr/zephyr.elf \ + /tmp/bloat_reports/ + + - name: clean out build output (keep tools) + run: rm -rf ./out/telink* + - name: Build example Telink (B92) Light Switch App with OTA (LZMA), Shell, Factory Data # Run test for master and all PRs run: | diff --git a/.github/workflows/examples-tizen.yaml b/.github/workflows/examples-tizen.yaml index f465f3999f..a16ad58ee0 100644 --- a/.github/workflows/examples-tizen.yaml +++ b/.github/workflows/examples-tizen.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen:90 + image: ghcr.io/project-chip/chip-build-tizen:92 options: --user root volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/full-android.yaml b/.github/workflows/full-android.yaml index 6acc150c03..a020b78d74 100644 --- a/.github/workflows/full-android.yaml +++ b/.github/workflows/full-android.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:90 + image: ghcr.io/project-chip/chip-build-android:92 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/fuzzing-build.yaml b/.github/workflows/fuzzing-build.yaml index f36b370448..97da04937e 100644 --- a/.github/workflows/fuzzing-build.yaml +++ b/.github/workflows/fuzzing-build.yaml @@ -33,7 +33,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index f416be3a4d..114f406f90 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-java:90 + image: ghcr.io/project-chip/chip-build-java:92 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 590a2595ee..9273dbe991 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 steps: - name: Checkout diff --git a/.github/workflows/minimal-build.yaml b/.github/workflows/minimal-build.yaml index da55158cc7..682cf3de20 100644 --- a/.github/workflows/minimal-build.yaml +++ b/.github/workflows/minimal-build.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:90 + image: ghcr.io/project-chip/chip-build-minimal:92 steps: - name: Checkout @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:90 + image: ghcr.io/project-chip/chip-build-minimal:92 steps: - name: Checkout diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml index 07b31eec0d..187d4b8f0c 100644 --- a/.github/workflows/qemu.yaml +++ b/.github/workflows/qemu.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif' container: - image: ghcr.io/project-chip/chip-build-esp32-qemu:90 + image: ghcr.io/project-chip/chip-build-esp32-qemu:92 volumes: - "/tmp/log_output:/tmp/test_logs" @@ -79,7 +79,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen-qemu:90 + image: ghcr.io/project-chip/chip-build-tizen-qemu:92 options: --user root volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/release_artifacts.yaml b/.github/workflows/release_artifacts.yaml index 14b2c32745..a50d5260b5 100644 --- a/.github/workflows/release_artifacts.yaml +++ b/.github/workflows/release_artifacts.yaml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-esp32:90 + image: ghcr.io/project-chip/chip-build-esp32:92 steps: - name: Checkout @@ -64,7 +64,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-efr32:90 + image: ghcr.io/project-chip/chip-build-efr32:92 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml index 38a614e712..c3293e8eb9 100644 --- a/.github/workflows/smoketest-android.yaml +++ b/.github/workflows/smoketest-android.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:90 + image: ghcr.io/project-chip/chip-build-android:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 9a31e56ca8..384ebc59a9 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -457,7 +457,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index b2fc345bda..9b97c8d54e 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/zap_regeneration.yaml b/.github/workflows/zap_regeneration.yaml index 0d6d9b6db7..649b867ba5 100644 --- a/.github/workflows/zap_regeneration.yaml +++ b/.github/workflows/zap_regeneration.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 defaults: run: shell: sh diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml index c4edd57421..07f1bc4f2f 100644 --- a/.github/workflows/zap_templates.yaml +++ b/.github/workflows/zap_templates.yaml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:90 + image: ghcr.io/project-chip/chip-build:92 defaults: run: shell: sh diff --git a/config/telink/chip-module/CMakeLists.txt b/config/telink/chip-module/CMakeLists.txt index ade2bd310f..0f925cdeff 100644 --- a/config/telink/chip-module/CMakeLists.txt +++ b/config/telink/chip-module/CMakeLists.txt @@ -174,7 +174,7 @@ add_dependencies(process_binaries ${ZEPHYR_FINAL_EXECUTABLE}) # Define 'build_mcuboot' target for building the MCUBoot bootloader # ============================================================================== -if (CONFIG_BOOTLOADER_MCUBOOT AND CONFIG_SOC_SERIES_RISCV_TELINK_B9X) +if (CONFIG_BOOTLOADER_MCUBOOT AND (CONFIG_SOC_SERIES_RISCV_TELINK_B9X OR CONFIG_SOC_SERIES_RISCV_TELINK_TLX)) add_custom_target(build_mcuboot ALL COMMAND west build -b ${BASE_BOARD} -d build_mcuboot ${ZEPHYR_BASE}/../bootloader/mcuboot/boot/zephyr diff --git a/config/telink/chip-module/Kconfig b/config/telink/chip-module/Kconfig index b06c7c8559..2937b2b0c6 100644 --- a/config/telink/chip-module/Kconfig +++ b/config/telink/chip-module/Kconfig @@ -246,7 +246,8 @@ config CHIP_ENABLE_POWER_ON_FACTORY_RESET config CHIP_TASK_STACK_SIZE int - default 4864 if PM + default 6192 if SOC_RISCV_TELINK_TL321X + default 5352 if PM default 8192 config CHIP_USE_MARS_SENSOR diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index bb722e8a3a..c220b5991f 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -34,6 +34,7 @@ choice LOG_MODE endchoice choice MATTER_LOG_LEVEL_CHOICE + default MATTER_LOG_LEVEL_WRN if SOC_RISCV_TELINK_TL321X default MATTER_LOG_LEVEL_DBG endchoice @@ -61,17 +62,19 @@ config POSIX_MAX_FDS # Application stack size config MAIN_STACK_SIZE - default 3240 if PM + default 3240 if PM || SOC_RISCV_TELINK_TL321X default 4096 config INIT_STACKS default y config IDLE_STACK_SIZE - default 512 if PM + default 512 if PM || SOC_RISCV_TELINK_TL321X + config ISR_STACK_SIZE default 576 if PM + default 528 if SOC_RISCV_TELINK_TL321X config SYSTEM_WORKQUEUE_STACK_SIZE default 616 if PM @@ -79,7 +82,8 @@ config SYSTEM_WORKQUEUE_STACK_SIZE config HEAP_MEM_POOL_SIZE default 256 -config COMMON_LIBC_MALLOC_ARENA_SIZE +config COMMON_LIBC_MALLOC_ARENA_SIZE + default 20716 if SOC_RISCV_TELINK_TL321X default 12288 config NET_IPV6_MLD @@ -92,19 +96,21 @@ config NET_IF_MCAST_IPV6_ADDR_COUNT # Network buffers config NET_PKT_RX_COUNT - default 4 if PM + default 4 if PM || SOC_RISCV_TELINK_TL321X default 8 config NET_PKT_TX_COUNT - default 4 if PM + default 4 if PM || SOC_RISCV_TELINK_TL321X default 8 config NET_BUF_RX_COUNT default 16 if PM + default 12 if SOC_RISCV_TELINK_TL321X default 32 config NET_BUF_TX_COUNT default 16 if PM + default 12 if SOC_RISCV_TELINK_TL321X default 32 config GPIO @@ -133,44 +139,71 @@ config BT_MAX_CONN default 1 config BT_L2CAP_TX_MTU + default 103 if SOC_RISCV_TELINK_TL321X default 247 config BT_BUF_ACL_RX_SIZE + default 107 if SOC_RISCV_TELINK_TL321X default 251 config BT_BUF_ACL_TX_SIZE + default 107 if SOC_RISCV_TELINK_TL321X default 251 + +#ifdef CONFIG_SOC_RISCV_TELINK_TL321X + +config BT_BUF_EVT_RX_COUNT + default 4 + +config BT_BUF_ACL_RX_COUNT + default 4 + +config BT_GATT_CACHING + bool + default n + + +#endif + config BT_RX_STACK_SIZE default 1352 if BT_B9X + default 1010 if BT_TLX default 2048 if BT_W91 config BT_HCI_TX_STACK_SIZE default 640 if BT_B9X + default 640 if BT_TLX default 2048 if BT_W91 config BT_DEVICE_NAME_GATT_WRITABLE bool default n -config B9X_BLE_CTRL_THREAD_STACK_SIZE +if SOC_SERIES_RISCV_TELINK_B9X || SOC_SERIES_RISCV_TELINK_TLX + +config TL_BLE_CTRL_THREAD_STACK_SIZE default 648 -config B9X_BLE_CTRL_MASTER_MAX_NUM +config TL_BLE_CTRL_MASTER_MAX_NUM default 0 -config B9X_BLE_CTRL_SLAVE_MAX_NUM +config TL_BLE_CTRL_SLAVE_MAX_NUM default 1 -config B9X_BLE_CTRL_RF_POWER +config TL_BLE_CTRL_RF_POWER default 3 if PM + default 8 if BT_TLX default 9 -choice B9X_BLE_CTRL_MAC_TYPE - default B9X_BLE_CTRL_MAC_TYPE_RANDOM_STATIC +choice TL_BLE_CTRL_MAC_TYPE + default TL_BLE_CTRL_MAC_TYPE_RANDOM_STATIC endchoice -endif +endif # SOC_SERIES_RISCV_TELINK_B9X || SOC_SERIES_RISCV_TELINK_TLX + + +endif # BT # Board retention config if BOARD_TLSR9528A_RETENTION || BOARD_TLSR9258A_RETENTION || BOARD_TLSR9518ADK80D_RETENTION @@ -182,11 +215,12 @@ config TELINK_B9X_MATTER_RETENTION_LAYOUT config PWM default n + endif # Board non-retention config if BOARD_TLSR9118BDK40D || BOARD_TLSR9118BDK40D_V1 || \ - BOARD_TLSR9528A || BOARD_TLSR9258A || BOARD_TLSR9518ADK80D + BOARD_TLSR9528A || BOARD_TLSR9258A || BOARD_TLSR9518ADK80D || BOARD_TL3218X config PWM default y endif @@ -222,6 +256,7 @@ config NVS_LOOKUP_CACHE default y config NVS_LOOKUP_CACHE_SIZE + default 400 if SOC_RISCV_TELINK_TL321X default 2048 if !PM # Set multiplicator of Name Value Storage (NVS) as 1 to reach NVS sector size 4KB @@ -261,7 +296,7 @@ config CHIP_ENABLE_ICD_SUPPORT default y if CHIP_THREAD_DEVICE_ROLE_SLEEPY_END_DEVICE config OPENTHREAD_THREAD_STACK_SIZE - default 2400 if PM + default 2400 if PM || SOC_RISCV_TELINK_TL321X config OPENTHREAD_RADIO_WORKQUEUE_STACK_SIZE default 432 if PM @@ -284,10 +319,10 @@ config OPENTHREAD_IP6_MAX_EXT_MCAST_ADDRS endif # NET_L2_OPENTHREAD config NET_TX_STACK_SIZE - default 554 if PM + default 554 if PM || SOC_RISCV_TELINK_TL321X config NET_RX_STACK_SIZE - default 554 if PM + default 554 if PM || SOC_RISCV_TELINK_TL321X # Disable certain parts of Zephyr IPv6 stack config NET_IPV6_NBR_CACHE diff --git a/examples/all-clusters-app/ameba/README.md b/examples/all-clusters-app/ameba/README.md index 5cf2c9aab8..53b4b6ce87 100644 --- a/examples/all-clusters-app/ameba/README.md +++ b/examples/all-clusters-app/ameba/README.md @@ -27,11 +27,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:92 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 - Setup build environment: diff --git a/examples/all-clusters-minimal-app/ameba/README.md b/examples/all-clusters-minimal-app/ameba/README.md index 447d950be3..f50cfee5e4 100644 --- a/examples/all-clusters-minimal-app/ameba/README.md +++ b/examples/all-clusters-minimal-app/ameba/README.md @@ -27,13 +27,13 @@ The CHIP demo application is supported on - Pull docker image: ``` - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:92 ``` - Run docker container: ``` - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 ``` - Setup build environment: diff --git a/examples/fabric-admin/README.md b/examples/fabric-admin/README.md index 92fdffda6b..d9fb67de46 100644 --- a/examples/fabric-admin/README.md +++ b/examples/fabric-admin/README.md @@ -23,13 +23,13 @@ For Raspberry Pi 4 example: ### Pull Docker Images ``` -docker pull ghcr.io/project-chip/chip-build-crosscompile:90 +docker pull ghcr.io/project-chip/chip-build-crosscompile:92 ``` ### Run docker ``` -docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash +docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:92 /bin/bash ``` ### Build diff --git a/examples/fabric-bridge-app/linux/README.md b/examples/fabric-bridge-app/linux/README.md index 912bb32c01..75f510da97 100644 --- a/examples/fabric-bridge-app/linux/README.md +++ b/examples/fabric-bridge-app/linux/README.md @@ -100,13 +100,13 @@ defined: Pull Docker Images ``` - docker pull ghcr.io/project-chip/chip-build-crosscompile:90 + docker pull ghcr.io/project-chip/chip-build-crosscompile:92 ``` Run docker ``` - docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:92 /bin/bash ``` Build diff --git a/examples/fabric-sync/README.md b/examples/fabric-sync/README.md index fd943e461f..bf4a3b0627 100644 --- a/examples/fabric-sync/README.md +++ b/examples/fabric-sync/README.md @@ -92,13 +92,13 @@ defined: Pull Docker Images ```sh - docker pull ghcr.io/project-chip/chip-build-crosscompile:90 + docker pull ghcr.io/project-chip/chip-build-crosscompile:92 ``` Run docker ```sh - docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:90 /bin/bash + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:92 /bin/bash ``` Build diff --git a/examples/light-switch-app/ameba/README.md b/examples/light-switch-app/ameba/README.md index ea9304fe7c..a499d29528 100644 --- a/examples/light-switch-app/ameba/README.md +++ b/examples/light-switch-app/ameba/README.md @@ -26,11 +26,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:92 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 - Setup build environment: diff --git a/examples/lighting-app/ameba/README.md b/examples/lighting-app/ameba/README.md index e91aec075b..ea6092575d 100644 --- a/examples/lighting-app/ameba/README.md +++ b/examples/lighting-app/ameba/README.md @@ -23,11 +23,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:92 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 - Setup build environment: diff --git a/examples/ota-requestor-app/ameba/README.md b/examples/ota-requestor-app/ameba/README.md index e748f41dc9..1f69815a78 100644 --- a/examples/ota-requestor-app/ameba/README.md +++ b/examples/ota-requestor-app/ameba/README.md @@ -6,11 +6,11 @@ A prototype application that demonstrates OTA Requestor capabilities. - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:92 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 - Setup build environment: diff --git a/examples/pigweed-app/ameba/README.md b/examples/pigweed-app/ameba/README.md index 136a37a14c..66d7564c2c 100644 --- a/examples/pigweed-app/ameba/README.md +++ b/examples/pigweed-app/ameba/README.md @@ -31,11 +31,11 @@ following features are available: - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:90 + $ docker pull ghcr.io/project-chip/chip-build-ameba:92 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:90 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 - Setup build environment: diff --git a/examples/platform/telink/common.cmake b/examples/platform/telink/common.cmake index 80050c81b3..b8da9a0dc8 100644 --- a/examples/platform/telink/common.cmake +++ b/examples/platform/telink/common.cmake @@ -72,7 +72,7 @@ if(NOT EXISTS "${BOOT_CONF_OVERLAY_FILE}") message(FATAL_ERROR "${BOOT_CONF_OVERLAY_FILE} doesn't exist") endif() -if(${CONFIG_USB_TELINK_B9X} MATCHES y) +if((${CONFIG_USB_TELINK_B9X} MATCHES y) OR (${CONFIG_USB_TELINK_TLX} MATCHES y)) set(BOOT_USB_CONF_OVERLAY_FILE "${CHIP_ROOT}/config/telink/app/bootloader_usb.conf") if(NOT EXISTS "${BOOT_USB_CONF_OVERLAY_FILE}") message(FATAL_ERROR "${BOOT_USB_CONF_OVERLAY_FILE} doesn't exist") diff --git a/examples/platform/telink/project_include/OpenThreadConfig.h b/examples/platform/telink/project_include/OpenThreadConfig.h index eabe238820..0e23617e28 100644 --- a/examples/platform/telink/project_include/OpenThreadConfig.h +++ b/examples/platform/telink/project_include/OpenThreadConfig.h @@ -27,12 +27,17 @@ /* Number of message buffers reduced to save RAM */ #undef OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS -#if CONFIG_PM +#if CONFIG_PM || CONFIG_SOC_RISCV_TELINK_TL321X #define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 22 #else #define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 44 #endif +#if CONFIG_SOC_RISCV_TELINK_TL321X +#undef OPENTHREAD_CONFIG_MLE_MAX_CHILDREN +#define OPENTHREAD_CONFIG_MLE_MAX_CHILDREN 5 +#endif + #define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_DEBUG_UART #undef OPENTHREAD_CONFIG_LOG_LEVEL diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index 1eafb85580..eba19f43d5 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -23,7 +23,7 @@ steps: - name: pwenv path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -38,7 +38,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index f1ca12766f..22b3d377d8 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -24,7 +24,7 @@ steps: path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -45,7 +45,7 @@ steps: volumes: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -66,7 +66,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -88,7 +88,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -141,7 +141,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:90" + - name: "ghcr.io/project-chip/chip-build-vscode:92" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 0f80756ec4..0bb25ef9a0 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -770,6 +770,7 @@ def BuildTelinkTarget(): TargetPart('tlsr9528a_retention', board=TelinkBoard.TLSR9528A_RETENTION), TargetPart('tlsr9258a', board=TelinkBoard.TLSR9258A), TargetPart('tlsr9258a_retention', board=TelinkBoard.TLSR9258A_RETENTION), + TargetPart('tl3218x', board=TelinkBoard.TL3218X), ]) target.AppendFixedTargets([ diff --git a/scripts/build/builders/telink.py b/scripts/build/builders/telink.py index a494300716..bf2bb1900a 100644 --- a/scripts/build/builders/telink.py +++ b/scripts/build/builders/telink.py @@ -121,6 +121,7 @@ class TelinkBoard(Enum): TLSR9528A_RETENTION = auto() TLSR9258A = auto() TLSR9258A_RETENTION = auto() + TL3218X = auto() def GnArgName(self): if self == TelinkBoard.TLRS9118BDK40D: @@ -135,6 +136,8 @@ def GnArgName(self): return 'tlsr9258a' elif self == TelinkBoard.TLSR9258A_RETENTION: return 'tlsr9258a_retention' + elif self == TelinkBoard.TL3218X: + return 'tl3218x' else: raise Exception('Unknown board type: %r' % self) diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index c473de1aa1..f3330ffc3f 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -22,5 +22,5 @@ nuttx-x64-light qpg-qpg6105-{lock,light,shell,persistent-storage,light-switch,thermostat}[-updateimage] stm32-stm32wb5mm-dk-light tizen-arm-{all-clusters,chip-tool,light,tests}[-no-ble][-no-thread][-no-wifi][-asan][-ubsan][-coverage][-with-ui] -telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma][-thread-analyzer] +telink-{tlsr9118bdk40d,tlsr9518adk80d,tlsr9528a,tlsr9528a_retention,tlsr9258a,tlsr9258a_retention,tl3218x}-{air-quality-sensor,all-clusters,all-clusters-minimal,bridge,contact-sensor,light,light-switch,lock,ota-requestor,pump,pump-controller,shell,smoke-co-alarm,temperature-measurement,thermostat,window-covering}[-ota][-dfu][-shell][-rpc][-factory-data][-4mb][-mars][-usb][-compress-lzma][-thread-analyzer] openiotsdk-{shell,lock}[-mbedtls][-psa] diff --git a/src/platform/telink/CHIPDevicePlatformConfig.h b/src/platform/telink/CHIPDevicePlatformConfig.h index 989b9b2aaf..3123d1464e 100644 --- a/src/platform/telink/CHIPDevicePlatformConfig.h +++ b/src/platform/telink/CHIPDevicePlatformConfig.h @@ -108,6 +108,12 @@ #define CHIP_DEVICE_CONFIG_ENABLE_ETHERNET 0 #endif // CHIP_DEVICE_CONFIG_ENABLE_ETHERNET +#ifdef CONFIG_SOC_RISCV_TELINK_TL321X +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE (256) +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE (256) +#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (256) +#endif + #ifdef CONFIG_BT #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE CONFIG_BT #else diff --git a/src/platform/telink/CHIPPlatformConfig.h b/src/platform/telink/CHIPPlatformConfig.h index edd68b9538..27b2104c24 100644 --- a/src/platform/telink/CHIPPlatformConfig.h +++ b/src/platform/telink/CHIPPlatformConfig.h @@ -62,7 +62,19 @@ #define CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS 1 #endif // CHIP_CONFIG_BDX_MAX_NUM_TRANSFERS -#ifdef CONFIG_PM +#ifdef CONFIG_SOC_RISCV_TELINK_TL321X + +#ifndef CHIP_CONFIG_MAX_GROUP_DATA_PEERS +#define CHIP_CONFIG_MAX_GROUP_DATA_PEERS 5 +#endif // CHIP_CONFIG_MAX_GROUP_DATA_PEERS + +#ifndef CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC +#define CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC 4 +#endif // CHIP_CONFIG_EXAMPLE_ACCESS_CONTROL_MAX_ENTRIES_PER_FABRIC + +#endif // CONFIG_SOC_RISCV_TELINK_TL321X + +#if defined CONFIG_PM || defined CONFIG_SOC_RISCV_TELINK_TL321X #ifndef CHIP_CONFIG_MAX_GROUP_DATA_PEERS #define CHIP_CONFIG_MAX_GROUP_DATA_PEERS 7 @@ -96,7 +108,7 @@ #define CHIP_CONFIG_DEVICE_MAX_ACTIVE_DEVICES 2 #endif // CHIP_CONFIG_DEVICE_MAX_ACTIVE_DEVICES -#endif // CONFIG_PM +#endif // CONFIG_PM || CONFIG_SOC_RISCV_TELINK_TL321X #ifndef CHIP_CONFIG_MAX_FABRICS #define CHIP_CONFIG_MAX_FABRICS 5 diff --git a/src/platform/telink/SystemPlatformConfig.h b/src/platform/telink/SystemPlatformConfig.h index 5a7b56e9af..462260e6d1 100644 --- a/src/platform/telink/SystemPlatformConfig.h +++ b/src/platform/telink/SystemPlatformConfig.h @@ -44,11 +44,18 @@ struct ChipDeviceEvent; #define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS +#ifdef CONFIG_SOC_RISCV_TELINK_TL321X +#define CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_HEAP 1 +#define CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL 0 +#define CHIP_SYSTEM_CONFIG_POOL_USE_HEAP 1 +#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX 1280 +#endif + #define CHIP_SYSTEM_CONFIG_USE_LWIP 0 #define CHIP_SYSTEM_CONFIG_USE_SOCKETS 1 // Reduce packet buffer pool size (default 15) to reduce ram consumption -#ifdef CONFIG_PM +#if defined CONFIG_PM || defined CONFIG_SOC_RISCV_TELINK_TL321X #define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 0 #else #define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 8 diff --git a/src/platform/telink/tl3218x.overlay b/src/platform/telink/tl3218x.overlay new file mode 100644 index 0000000000..4c74bb14ea --- /dev/null +++ b/src/platform/telink/tl3218x.overlay @@ -0,0 +1,61 @@ +/ { + /* Short TL_Key3 (J6 pin 21) to ground */ + key_pool { + compatible = "gpio-keys"; + + inp { + gpios = <&gpiob 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, + <&gpiob 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + + key_matrix { + compatible = "gpio-keys"; + + col { + gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>, + <&gpiob 7 GPIO_ACTIVE_HIGH>; + }; + + row { + gpios = <&gpiob 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpiob 5 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + }; + }; + + led_pool { + compatible = "gpio-leds"; + + out { + gpios = <&gpiod 0 GPIO_ACTIVE_HIGH>; + }; + }; + + pwm_pool { + compatible = "pwm-leds"; + out { + pwms = <&pwm0 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>, + <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>, + <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pwm0 { + /* On board RGB LEDs */ + pinctrl-ch0 = <&pwm_ch0_pb1_default>; + pinctrl-ch2 = <&pwm_ch1_pb2_default>; + pinctrl-ch1 = <&pwm_ch2_pb0_default>; +}; + +&pinctrl { + pwm_ch0_pb1_default: pwm_ch0_pb1_default { + pinmux = ; + }; + pwm_ch1_pb2_default: pwm_ch1_pb2_default { + pinmux = ; + }; + pwm_ch2_pb0_default: pwm_ch2_pb0_default { + pinmux = ; + }; +}; diff --git a/src/platform/telink/tl3218x_2m_flash.overlay b/src/platform/telink/tl3218x_2m_flash.overlay new file mode 100644 index 0000000000..53114e6ac6 --- /dev/null +++ b/src/platform/telink/tl3218x_2m_flash.overlay @@ -0,0 +1,39 @@ +&flash { + reg = <0x20000000 0x200000>; + + /delete-node/ partitions; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x13000>; + }; + slot0_partition: partition@13000 { + label = "image-0"; + reg = <0x13000 0xef000>; + }; + factory_partition: partition@102000 { + label = "factory-data"; + reg = <0x102000 0x800>; + }; + factory_rfu_partition: partition@102800 { + label = "factory-data-rfu"; + reg = <0x102800 0x800>; + }; + storage_partition: partition@103000 { + label = "storage"; + reg = <0x103000 0xc000>; + }; + slot1_partition: partition@10f000 { + label = "image-1"; + reg = <0x10f000 0xef000>; + }; + vendor_partition: partition@1fe000 { + label = "vendor-data"; + reg = <0x1fe000 0x2000>; + }; + }; +}; From 649c19f039277c7aeedf4ac060425890da9002b2 Mon Sep 17 00:00:00 2001 From: andrei-menzopol <96489227+andrei-menzopol@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:29:19 +0200 Subject: [PATCH 040/219] [nxp][examples][contact-sensor][zap] Update zap files (#36513) * [nxp][examples][contact-sensor][zap] Update zap files * Update cluster version * Update AccessControl feature map * Add OTA Requestor device type to EP0 * [nxp][examples][contact-sensor][zap] Disable Extension ACL attribute Signed-off-by: Andrei Menzopol --------- Signed-off-by: Andrei Menzopol --- .../nxp/zap-lit/contact-sensor-app.matter | 27 +- .../nxp/zap-lit/contact-sensor-app.zap | 439 +++++++++++------- .../nxp/zap-sit/contact-sensor-app.matter | 27 +- .../nxp/zap-sit/contact-sensor-app.zap | 437 ++++++++++------- 4 files changed, 573 insertions(+), 357 deletions(-) diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter index dd5f9ab061..899dc159a0 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.matter @@ -1724,6 +1724,7 @@ cluster IcdManagement = 70 { endpoint 0 { device type ma_rootdevice = 22, version 2; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -1732,6 +1733,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -1740,7 +1744,6 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; @@ -1774,7 +1777,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -1785,6 +1788,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1801,7 +1807,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -1826,7 +1832,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -1943,7 +1949,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x000F; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ResetCounts; } @@ -1952,6 +1958,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1966,6 +1975,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1988,6 +2000,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2034,7 +2049,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; diff --git a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap index dfbd44ad6e..6658c278e9 100644 --- a/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-lit/contact-sensor-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,21 +41,32 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + }, + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 1 } ], "deviceVersions": [ - 2 + 2, + 1 ], "deviceIdentifiers": [ - 22 + 22, + 18 ], "deviceTypeName": "MA-rootdevice", "deviceTypeCode": 22, @@ -133,6 +144,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -191,22 +250,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "Extension", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SubjectsPerAccessControlEntry", "code": 2, @@ -287,22 +330,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -649,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -707,7 +718,7 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -870,6 +881,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1097,22 +1156,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1155,7 +1198,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1429,22 +1472,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1487,7 +1514,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1553,22 +1580,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1765,22 +1776,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2966,22 +2961,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3024,7 +3003,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3106,6 +3085,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3342,6 +3369,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3498,6 +3573,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3736,7 +3859,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3774,22 +3897,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3849,14 +3956,16 @@ "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -4001,7 +4110,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4219,22 +4328,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter index 1cd10f3571..3c88ebe120 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.matter @@ -1724,6 +1724,7 @@ cluster IcdManagement = 70 { endpoint 0 { device type ma_rootdevice = 22, version 2; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -1732,6 +1733,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -1740,7 +1744,6 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; @@ -1774,7 +1777,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -1785,6 +1788,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1801,7 +1807,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -1826,7 +1832,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -1943,7 +1949,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x000F; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ResetCounts; } @@ -1952,6 +1958,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1966,6 +1975,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -1988,6 +2000,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2021,7 +2036,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; diff --git a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap index 56717f4edf..3110fe05f2 100644 --- a/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap +++ b/examples/contact-sensor-app/nxp/zap-sit/contact-sensor-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,21 +41,32 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 + }, + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 1 } ], "deviceVersions": [ - 2 + 2, + 1 ], "deviceIdentifiers": [ - 22 + 22, + 18 ], "deviceTypeName": "MA-rootdevice", "deviceTypeCode": 22, @@ -133,6 +144,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -191,22 +250,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "Extension", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SubjectsPerAccessControlEntry", "code": 2, @@ -287,22 +330,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -649,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -707,7 +718,7 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -870,6 +881,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1097,22 +1156,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1155,7 +1198,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1429,22 +1472,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1487,7 +1514,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1553,22 +1580,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1765,22 +1776,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2966,22 +2961,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3024,7 +3003,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3106,6 +3085,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3342,6 +3369,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3498,6 +3573,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3620,22 +3743,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3695,14 +3802,16 @@ "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 21, "profileId": 259, "label": "MA-contactsensor", - "name": "MA-contactsensor" + "name": "MA-contactsensor", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -3847,7 +3956,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4065,22 +4174,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, From 5cd0c0dcf4905b82863c491334d0bb9d4038c8ac Mon Sep 17 00:00:00 2001 From: Terence Hampson Date: Tue, 19 Nov 2024 09:40:28 -0500 Subject: [PATCH 041/219] Add unit test for deleting CommandSender when response is pending (#36536) --- src/app/tests/TestCommandInteraction.cpp | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index 4535a51dff..363b43ccb4 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -1554,6 +1554,43 @@ TEST_F(TestCommandInteraction, TestCommandSenderCommandAsyncSuccessResponseFlow) EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); } +TEST_F(TestCommandInteraction, CommandSenderDeletedWhenResponseIsPending) +{ + + mockCommandSenderDelegate.ResetCounter(); + app::CommandSender * commandSender = Platform::New(&mockCommandSenderDelegate, &GetExchangeManager()); + + AddInvokeRequestData(commandSender); + asyncCommand = true; + + EXPECT_EQ(commandSender->SendCommandRequest(GetSessionBobToAlice()), CHIP_NO_ERROR); + + DrainAndServiceIO(); + + EXPECT_EQ(mockCommandSenderDelegate.onResponseCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 0); + EXPECT_EQ(GetNumActiveCommandResponderObjects(), 1u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 2u); + + // This is NOT deleting CommandSender in one of the callbacks, so we are not violating + // the API contract. CommandSender is deleted when no message is being processed which + // is a time that deleting CommandSender is considered safe. + Platform::Delete(commandSender); + + // Decrease CommandHandler refcount and send response + asyncCommandHandle = nullptr; + + DrainAndServiceIO(); + + EXPECT_EQ(mockCommandSenderDelegate.onResponseCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onFinalCalledTimes, 0); + EXPECT_EQ(mockCommandSenderDelegate.onErrorCalledTimes, 0); + + EXPECT_EQ(GetNumActiveCommandResponderObjects(), 0u); + EXPECT_EQ(GetExchangeManager().GetNumActiveExchanges(), 0u); +} + TEST_F(TestCommandInteraction, TestCommandSenderCommandSpecificResponseFlow) { From 29f008ee9610131aa4eaa66842cd0f9af025ff05 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Tue, 19 Nov 2024 11:58:21 -0500 Subject: [PATCH 042/219] TC-IDM-4.2: Remove yaml, now has a python impl (#36518) --- .../suites/certification/Test_TC_IDM_4_2.yaml | 774 ------------------ src/app/tests/suites/manualTests.json | 1 - 2 files changed, 775 deletions(-) delete mode 100644 src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml diff --git a/src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml b/src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml deleted file mode 100644 index 21beac03a8..0000000000 --- a/src/app/tests/suites/certification/Test_TC_IDM_4_2.yaml +++ /dev/null @@ -1,774 +0,0 @@ -# Copyright (c) 2023 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. -# Auto-generated scripts for harness use only, please review before automation. The endpoints and cluster names are currently set to default - -name: - 32.4.2. [TC-IDM-4.2] Subscription Response Messages from DUT Test Cases. - [DUT as Server] - -PICS: - - MCORE.IDM.S - -config: - nodeId: 0x12344321 - cluster: "Basic Information" - endpoint: 0 - -tests: - - label: "Notes/Testing Considerations" - verification: | - 1. The Cluster and Commands should be based on the cluster implementation on the DUT. - 2. The cluster used in the below test steps is an example, User can use any supported chip cluster/attribute/command. - disabled: true - - - label: "Pre condition" - verification: | - Please use Interactive mode to Verify subscription test cases - Here the command to enter interactive mode:-- ./chip-tool interactive start - disabled: true - - - label: "Step 0a: SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT = 60 mins" - PICS: " !ICDM.S " - verification: | - When the ICDM feature is not supported or enabled, the SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT is set to 60 minutes. - disabled: true - - - label: "Step 0b: CR1 reads from the DUT the IdleModeDuration attribute." - PICS: ICDM.S - verification: | - CR1 reads from the DUT the IdleModeDuration attribute by sending below mentioned command - - icdmanagement read idle-mode-interval 1 0 - - Please note down the value of IdleModeDuration as SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT for use in the next step validations. - - [1692870543.225457][7160:7162] CHIP:DMG: SuppressResponse = true, - [1692870543.225495][7160:7162] CHIP:DMG: InteractionModelRevision = 10 - [1692870543.225528][7160:7162] CHIP:DMG: } - [1692870543.225723][7160:7162] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0046 Attribute 0x0000_0000 DataVersion: 4022467249 - [1692870543.225795][7160:7162] CHIP:TOO: IdleModeDuration: 2000 - [1692870543.225992][7160:7162] CHIP:EM: <<< [E:52837i S:57653 M:52559591 (Ack:263018291)] (S) Msg TX to 1:0000000000000001 [853D] --- Type 0000:10 (SecureChannel:StandaloneAck) - disabled: true - - - label: - "Step 1: CR1 sends a subscription message to the DUT with - MaxIntervalCeiling set to a value greater than - SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. DUT sends a report data - action to the TH. CR1 sends a success status response to the DUT. DUT - sends a Subscribe Response Message to the CR1 to activate the - subscription." - verification: | - Please run the following command on the TH to test the subscription feature and verify that the value of MaxIntervalCeiling is set correctly(set the value greater than SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT) - - onoff subscribe on-off 100 600 1 1 --keepSubscriptions true - - On the CR1( chip-tool), verify a report data message is received and verify it contains the following data : - 1. Verify Report Data Message Received: - Check if a report data message is received on the CR1. - - 2. Verify Report Data Contents: - Confirm that the received report data message contains the data of the attribute/event that was previously requested. - - 3. Verify Subscribe Response Fields: - Examine the Subscribe Response to ensure it includes the following fields: - SubscriptionId: Verify that it is of type uint32. - Verify MaxInterval Field: - - 4. Check for an additional field in the Subscribe Response: - MaxInterval: Verify that it is of type uint32. - - 5. Verify MaxInterval against MaxIntervalCeiling: - Compare the MaxInterval value received in the Subscribe Response to the MaxIntervalCeiling value to verify that MaxInterval is less than or equal to MaxIntervalCeiling. - - [1693221742.765461][22261:22263] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0006 Attribute 0x0000_0000 DataVersion: 523169586 - [1693221742.765473][22261:22263] CHIP:TOO: OnOff: FALSE - [1693221742.765495][22261:22263] CHIP:DMG: MoveToState ReadClient[0x7f6070027e40]: Moving to [AwaitingSu] - [1693221742.765530][22261:22263] CHIP:EM: <<< [E:26388i S:13043 M:192043500 (Ack:11734613)] (S) Msg TX to 1:0000000000000001 [3DC0] --- Type 0001:01 (IM:StatusResponse) - [1693221742.765542][22261:22263] CHIP:IN: (S) Sending msg 192043500 on secure session with LSID: 13043 - [1693221742.765587][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221742.765594][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221742.765981][22261:22263] CHIP:EM: >>> [E:26388i S:13043 M:11734614 (Ack:192043500)] (S) Msg RX from 1:0000000000000001 [3DC0] --- Type 0001:04 (IM:SubscribeResponse) - [1693221742.765991][22261:22263] CHIP:EM: Found matching exchange: 26388i, Delegate: 0x7f6070027e50 - [1693221742.766002][22261:22263] CHIP:EM: Rxd Ack; Removing MessageCounter:192043500 from Retrans Table on exchange 26388i - [1693221742.766012][22261:22263] CHIP:DMG: SubscribeResponse is received - [1693221742.766025][22261:22263] CHIP:DMG: SubscribeResponseMessage = - [1693221742.766031][22261:22263] CHIP:DMG: { - [1693221742.766038][22261:22263] CHIP:DMG: SubscriptionId = 0x15e2f82f, - [1693221742.766045][22261:22263] CHIP:DMG: MaxInterval = 0x64, - [1693221742.766051][22261:22263] CHIP:DMG: InteractionModelRevision = 10 - [1693221742.766057][22261:22263] CHIP:DMG: } - [1693221742.766068][22261:22263] CHIP:DMG: Subscription established with SubscriptionID = 0x15e2f82f MinInterval = 100s MaxInterval = 100s Peer = 01:0000000000000001 - disabled: true - - - label: - "Step 2: CR1 sends a subscription message to the DUT with - MaxIntervalCeiling set to a value less than - SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. DUT sends a report data - action to the CR1. CR1 sends a success status response to the DUT. DUT - sends a Subscribe Response Message to the CR1 to activate the - subscription." - verification: | - Please run the following command on the TH to test the subscription feature and verify that the value of MaxIntervalCeiling is set correctly( set the value less than SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT) - - - basicinformation subscribe location 10 400 1 0 --keepSubscriptions true - - On the CR1(chip-tool), verify a report data message is received and verify it contains the following data : - 1. Verify Report Data Message Received: - Check if a report data message is received on the CR1 (target hardware). - - 2. Verify Report Data Contents: - Confirm that the received report data message contains the data of the attribute/event that was previously requested. - - 3. Verify Subscribe Response Fields: - Examine the Subscribe Response to ensure it includes the following fields: - SubscriptionId: Verify that it is of type uint32. - MaxInterval: Verify that it is of type uint32. - - 4. Verify MaxInterval against SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT: - Compare the MaxInterval value received in the Subscribe Response to the value of SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. - Verify that the MaxInterval value is less than or equal to SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT. - - [1693221766.862968][22261:22263] CHIP:DMG: } - [1693221766.863028][22261:22263] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0028 Attribute 0x0000_0006 DataVersion: 1552486032 - [1693221766.863045][22261:22263] CHIP:TOO: Location: XX - [1693221766.863068][22261:22263] CHIP:DMG: MoveToState ReadClient[0x7f6070027b50]: Moving to [AwaitingSu] - [1693221766.863114][22261:22263] CHIP:EM: <<< [E:26389i S:13043 M:192043503 (Ack:11734615)] (S) Msg TX to 1:0000000000000001 [3DC0] --- Type 0001:01 (IM:StatusResponse) - [1693221766.863130][22261:22263] CHIP:IN: (S) Sending msg 192043503 on secure session with LSID: 13043 - [1693221766.863196][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221766.863207][22261:22263] CHIP:DL: HandlePlatformSpecificBLEEvent 32793 - [1693221766.863559][22261:22263] CHIP:EM: >>> [E:26389i S:13043 M:11734616 (Ack:192043503)] (S) Msg RX from 1:0000000000000001 [3DC0] --- Type 0001:04 (IM:SubscribeResponse) - [1693221766.863569][22261:22263] CHIP:EM: Found matching exchange: 26389i, Delegate: 0x7f6070027b60 - [1693221766.863584][22261:22263] CHIP:EM: Rxd Ack; Removing MessageCounter:192043503 from Retrans Table on exchange 26389i - [1693221766.863603][22261:22263] CHIP:DMG: SubscribeResponse is received - [1693221766.863620][22261:22263] CHIP:DMG: SubscribeResponseMessage = - [1693221766.863629][22261:22263] CHIP:DMG: { - [1693221766.863639][22261:22263] CHIP:DMG: SubscriptionId = 0x83e461d9, - [1693221766.863651][22261:22263] CHIP:DMG: MaxInterval = 0xa, - [1693221766.863661][22261:22263] CHIP:DMG: InteractionModelRevision = 10 - [1693221766.863667][22261:22263] CHIP:DMG: } - [1693221766.863677][22261:22263] CHIP:DMG: Subscription established with SubscriptionID = 0x83e461d9 MinInterval = 10s MaxInterval = 10s Peer = 01:0000000000000001 - disabled: true - - - label: - "Step 3: Setup CR2 such that it does not have access to a specific - cluster. CR2 sends a subscription message to subscribe to an attribute - on that cluster for which it does not have access. AttributePath = - [[Attribute = Attribute, Cluster = ClusterID, Endpoint = EndpointID - ]]." - verification: | - To ensure that CR1 and CR2 are on the same fabric and that CR1 grants access to CR2, Please send the below mentioned command, it will configure TH2 without access to a specific cluster, we send the ACL command, allowing access only to the Level Control cluster (cluster ID: 8); any attempts to subscribe to or use commands from other clusters will result in a status of 'INVALID_ACTION - - accesscontrol write acl '[{"privilege":5, "authMode":2, "subjects":[112233], "targets":null, "fabricIndex": 1},{"privilege":3, "authMode":2, "subjects":[4], "targets":[{"cluster":8, "endpoint":null, "deviceType":null}]}]' 1 0 - - [1689933254.566655][48781:48783] CHIP:EM: Rxd Ack; Removing MessageCounter:156974239 from Retrans Table on exchange 6316i - [1689933254.566660][48781:48783] CHIP:DMG: WriteClient moving to [ResponseRe] - [1689933254.566671][48781:48783] CHIP:DMG: WriteResponseMessage = - [1689933254.566675][48781:48783] CHIP:DMG: { - [1689933254.566677][48781:48783] CHIP:DMG: AttributeStatusIBs = - [1689933254.566682][48781:48783] CHIP:DMG: [ - [1689933254.566684][48781:48783] CHIP:DMG: AttributeStatusIB = - [1689933254.566688][48781:48783] CHIP:DMG: { - [1689933254.566691][48781:48783] CHIP:DMG: AttributePathIB = - [1689933254.566695][48781:48783] CHIP:DMG: { - [1689933254.566698][48781:48783] CHIP:DMG: Endpoint = 0x0, - [1689933254.566702][48781:48783] CHIP:DMG: Cluster = 0x1f, - [1689933254.566705][48781:48783] CHIP:DMG: Attribute = 0x0000_0000, - [1689933254.566708][48781:48783] CHIP:DMG: } - [1689933254.566713][48781:48783] CHIP:DMG: - [1689933254.566716][48781:48783] CHIP:DMG: StatusIB = - [1689933254.566720][48781:48783] CHIP:DMG: { - [1689933254.566723][48781:48783] CHIP:DMG: status = 0x00 (SUCCESS), - [1689933254.566726][48781:48783] CHIP:DMG: }, - [1689933254.566730][48781:48783] CHIP:DMG: - [1689933254.566732][48781:48783] CHIP:DMG: }, - [1689933254.566739][48781:48783] CHIP:DMG: - [1689933254.566741][48781:48783] CHIP:DMG: AttributeStatusIB = - [1689933254.566744][48781:48783] CHIP:DMG: { - [1689933254.566747][48781:48783] CHIP:DMG: AttributePathIB = - [1689933254.566750][48781:48783] CHIP:DMG: { - [1689933254.566752][48781:48783] CHIP:DMG: Endpoint = 0x0, - [1689933254.566756][48781:48783] CHIP:DMG: Cluster = 0x1f, - [1689933254.566760][48781:48783] CHIP:DMG: Attribute = 0x0000_0000, - [1689933254.566763][48781:48783] CHIP:DMG: ListIndex = Null, - [1689933254.566766][48781:48783] CHIP:DMG: } - [1689933254.566770][48781:48783] CHIP:DMG: - [1689933254.566773][48781:48783] CHIP:DMG: StatusIB = - [1689933254.566776][48781:48783] CHIP:DMG: { - [1689933254.566779][48781:48783] CHIP:DMG: status = 0x00 (SUCCESS), - [1689933254.566782][48781:48783] CHIP:DMG: }, - [1689933254.566786][48781:48783] CHIP:DMG: - [1689933254.566789][48781:48783] CHIP:DMG: }, - [1689933254.566794][48781:48783] CHIP:DMG: - [1689933254.566797][48781:48783] CHIP:DMG: AttributeStatusIB = - [1689933254.566800][48781:48783] CHIP:DMG: { - [1689933254.566802][48781:48783] CHIP:DMG: AttributePathIB = - [1689933254.566805][48781:48783] CHIP:DMG: { - [1689933254.566808][48781:48783] CHIP:DMG: Endpoint = 0x0, - [1689933254.566811][48781:48783] CHIP:DMG: Cluster = 0x1f, - [1689933254.566815][48781:48783] CHIP:DMG: Attribute = 0x0000_0000, - [1689933254.566818][48781:48783] CHIP:DMG: ListIndex = Null, - [1689933254.566821][48781:48783] CHIP:DMG: } - [1689933254.566825][48781:48783] CHIP:DMG: - [1689933254.566828][48781:48783] CHIP:DMG: StatusIB = - [1689933254.566831][48781:48783] CHIP:DMG: { - [1689933254.566834][48781:48783] CHIP:DMG: status = 0x00 (SUCCESS), - [1689933254.566837][48781:48783] CHIP:DMG: }, - [1689933254.566840][48781:48783] CHIP:DMG: - [1689933254.566843][48781:48783] CHIP:DMG: }, - [1689933254.566847][48781:48783] CHIP:DMG: - [1689933254.566849][48781:48783] CHIP:DMG: ], - [1689933254.566857][48781:48783] CHIP:DMG: - [1689933254.566859][48781:48783] CHIP:DMG: InteractionModelRevision = 1 - [1689933254.566862][48781:48783] CHIP:DMG: } - [1689933254.566897][48781:48783] CHIP:DMG: WriteClient moving to [AwaitingDe] - [1689933254.566916][48781:48783] CHIP:EM: <<< [E:6316i S:13964 M:156974240 (Ack:46397313)] (S) Msg TX to 1:0000000000000001 [B15F] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1689933254.566922][48781:48783] CHIP:IN: (S) Sending msg 156974240 on secure session with LSID: 13964 - - If CR2 attempts to subscribe to an attribute on a cluster (ClusterID) for which it does not have access, the AttributePath used for the subscription would be in the form [[Attribute = AttributeName, Cluster = ClusterID, Endpoint = EndpointID]], but this action will be denied, and CR2 will not be able to access the attribute due to the restricted access. - - below provided the example command used to subscribe location attribute from basicinformation cluster from node id(4) that have access to the “levelcontrol” cluster - - basicinformation subscribe location 10 2400 1 0 --commissioner-nodeid 4 - [1689933387.304826][48781:48783] CHIP:EM: Rxd Ack; Removing MessageCounter:42350588 from Retrans Table on exchange 6319i - [1689933387.304834][48781:48783] CHIP:DMG: StatusResponseMessage = - [1689933387.304838][48781:48783] CHIP:DMG: { - [1689933387.304841][48781:48783] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1689933387.304845][48781:48783] CHIP:DMG: InteractionModelRevision = 1 - [1689933387.304846][48781:48783] CHIP:DMG: } - [1689933387.304850][48781:48783] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1689933387.304864][48781:48783] CHIP:EM: <<< [E:6319i S:13965 M:42350589 (Ack:227168589)] (S) Msg TX to 2:0000000000000001 [B15F] --- Type 0001:01 (IM:StatusResponse) - [1689933387.304869][48781:48783] CHIP:IN: (S) Sending msg 42350589 on secure session with LSID: 13965 - [1689933387.304882][48781:48783] CHIP:DMG: MoveToState ReadClient[0x7fd404019110]: Moving to [ Idle] - - With the ACL command in step-2, we are overwriting the default privilege that chip-tool has an admin. After this step-3 you need to send below mentioned command to Grant access to all clusters again. - accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode":2, "subjects":[112233,4], "targets":null}]' 1 0 - disabled: true - - - label: - "Step 4: Setup CR2 such that it does not have access to all attributes - on a specific cluster and endpoint. CR2 sends a subscription request - to subscribe to all attributes for which it does not have access. - AttributePath = [[Cluster = ClusterID, Endpoint = EndpointID ]]." - verification: | - To ensure that CR1 and CR2 are on the same fabric and that CR1 grants access to CR2, Please send the below mentioned command, it will configure CR2 without access to a specific cluster on Specific endpoint, we send the ACL command, allowing access only to the Level Control cluster (cluster ID: 8) on endpoint 1 ; any attempts to subscribe to or use commands from other clusters will result in a status of 'INVALID_ACTION - - accesscontrol write acl '[{"privilege":5, "authMode":2, "subjects":[112233], "targets":null, "fabricIndex": 1},{"privilege":3, "authMode":2, "subjects":[4], "targets":[{"cluster":8, "endpoint":1, "deviceType":null}]}]' 1 0 - - [1687418564.590285][167960:167962] CHIP:DMG: WriteResponseMessage = - [1687418564.590290][167960:167962] CHIP:DMG: { - [1687418564.590294][167960:167962] CHIP:DMG: AttributeStatusIBs = - [1687418564.590304][167960:167962] CHIP:DMG: [ - [1687418564.590313][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418564.590321][167960:167962] CHIP:DMG: { - [1687418564.590327][167960:167962] CHIP:DMG: AttributePathIB = - [1687418564.590336][167960:167962] CHIP:DMG: { - [1687418564.590346][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418564.590355][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418564.590366][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418564.590374][167960:167962] CHIP:DMG: } - [1687418564.590385][167960:167962] CHIP:DMG: - [1687418564.590392][167960:167962] CHIP:DMG: StatusIB = - [1687418564.590406][167960:167962] CHIP:DMG: { - [1687418564.590415][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418564.590423][167960:167962] CHIP:DMG: }, - [1687418564.590433][167960:167962] CHIP:DMG: - [1687418564.590444][167960:167962] CHIP:DMG: }, - [1687418564.590462][167960:167962] CHIP:DMG: - [1687418564.590469][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418564.590477][167960:167962] CHIP:DMG: { - [1687418564.590484][167960:167962] CHIP:DMG: AttributePathIB = - [1687418564.590493][167960:167962] CHIP:DMG: { - [1687418564.590502][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418564.590512][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418564.590521][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418564.590530][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418564.590539][167960:167962] CHIP:DMG: } - [1687418564.590552][167960:167962] CHIP:DMG: - [1687418564.590559][167960:167962] CHIP:DMG: StatusIB = - [1687418564.590567][167960:167962] CHIP:DMG: { - [1687418564.590576][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418564.590584][167960:167962] CHIP:DMG: }, - [1687418564.590593][167960:167962] CHIP:DMG: - [1687418564.590601][167960:167962] CHIP:DMG: }, - [1687418564.590616][167960:167962] CHIP:DMG: - [1687418564.590623][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418564.590631][167960:167962] CHIP:DMG: { - [1687418564.590638][167960:167962] CHIP:DMG: AttributePathIB = - [1687418564.590647][167960:167962] CHIP:DMG: { - [1687418564.590656][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418564.590665][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418564.590675][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418564.590683][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418564.590691][167960:167962] CHIP:DMG: } - [1687418564.590704][167960:167962] CHIP:DMG: - [1687418564.590712][167960:167962] CHIP:DMG: StatusIB = - [1687418564.590720][167960:167962] CHIP:DMG: { - [1687418564.590729][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418564.590738][167960:167962] CHIP:DMG: }, - [1687418564.590747][167960:167962] CHIP:DMG: - [1687418564.590754][167960:167962] CHIP:DMG: }, - [1687418564.590768][167960:167962] CHIP:DMG: - [1687418564.590776][167960:167962] CHIP:DMG: ], - [1687418564.590796][167960:167962] CHIP:DMG: - [1687418564.590804][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418564.590811][167960:167962] CHIP:DMG: } - [1687418564.590882][167960:167962] CHIP:DMG: WriteClient moving to [AwaitingDe] - - If CR2 attempts to subscribe to an attribute on a cluster (ClusterID) for which it does not have access, the AttributePath used for the subscription would be in the form AttributePath = [[Cluster = ClusterID, Endpoint = EndpointID ]]., but this action will be denied, and CR2 will not be able to access the attribute due to the restricted access. - - below provided the example command to subscribe all attributes onto endpoint 1 for onoff cluster from node id(4) that have access to the “levelcontrol” cluster onto endpoint 1 - - - - onoff subscribe-by-id 0xFFFFFFFF 5 100 1 1 --commissioner-nodeid 4 - [1687418591.903193][167960:167962] CHIP:EM: Found matching exchange: 3641i, Delegate: 0x7fc81c00bbd0 - [1687418591.903197][167960:167962] CHIP:EM: Rxd Ack; Removing MessageCounter:104560060 from Retrans Table on exchange 3641i - [1687418591.903206][167960:167962] CHIP:DMG: StatusResponseMessage = - [1687418591.903209][167960:167962] CHIP:DMG: { - [1687418591.903211][167960:167962] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1687418591.903213][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418591.903215][167960:167962] CHIP:DMG: } - [1687418591.903220][167960:167962] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1687418591.903236][167960:167962] CHIP:EM: <<< [E:3641i S:26604 M:104560061 (Ack:37058090)] (S) Msg TX to 2:0000000000000001 [2DB4] --- Type 0001:01 (IM:StatusResponse) - [1687418591.903241][167960:167962] CHIP:IN: (S) Sending msg 104560061 on secure session with LSID: 26604 - [1687418591.903262][167960:167962] CHIP:DMG: MoveToState ReadClient[0x7fc81c00bbc0]: Moving to - - With the ACL command in step-2, we are overwriting the default privilege that chip-tool has an admin. After this step-3 you need to send below mentioned command to Grant access to all clusters again. - - accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode":2, "subjects":[112233,4], "targets":null}]' 1 0 - disabled: true - - - label: - "Step 5: Setup CR2 such that it does not have access to an Endpoint. - CR2 sends a subscription request to subscribe to all attributes on all - clusters on a specific Endpoint for which it does not have access. - AttributePath = [[ Endpoint = EndpointID ]]." - verification: | - To ensure that CR1 and CR2 are on the same fabric and that CR1 grants access to CR2, Please send the below mentioned command, it will configure CR2 without access to a specific endpoint, we send the ACL command, allowing access only to the endpoint 1 ; any attempts to subscribe to or use commands from other clusters will result in a status of 'INVALID_ACTION - - accesscontrol write acl '[{"privilege":5, "authMode":2, "subjects":[112233], "targets":null, "fabricIndex": 1},{"privilege":3, "authMode":2, "subjects":[4], "targets":[{"cluster":null, "endpoint":1, "deviceType":null}]}]' 1 0 - - [1687418943.852982][167960:167962] CHIP:DMG: WriteResponseMessage = - [1687418943.852989][167960:167962] CHIP:DMG: { - [1687418943.852996][167960:167962] CHIP:DMG: AttributeStatusIBs = - [1687418943.853006][167960:167962] CHIP:DMG: [ - [1687418943.853012][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418943.853018][167960:167962] CHIP:DMG: { - [1687418943.853024][167960:167962] CHIP:DMG: AttributePathIB = - [1687418943.853034][167960:167962] CHIP:DMG: { - [1687418943.853042][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418943.853053][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418943.853060][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418943.853067][167960:167962] CHIP:DMG: } - [1687418943.853080][167960:167962] CHIP:DMG: - [1687418943.853087][167960:167962] CHIP:DMG: StatusIB = - [1687418943.853095][167960:167962] CHIP:DMG: { - [1687418943.853103][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418943.853109][167960:167962] CHIP:DMG: }, - [1687418943.853117][167960:167962] CHIP:DMG: - [1687418943.853123][167960:167962] CHIP:DMG: }, - [1687418943.853136][167960:167962] CHIP:DMG: - [1687418943.853142][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418943.853148][167960:167962] CHIP:DMG: { - [1687418943.853154][167960:167962] CHIP:DMG: AttributePathIB = - [1687418943.853161][167960:167962] CHIP:DMG: { - [1687418943.853167][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418943.853175][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418943.853182][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418943.853189][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418943.853196][167960:167962] CHIP:DMG: } - [1687418943.853205][167960:167962] CHIP:DMG: - [1687418943.853211][167960:167962] CHIP:DMG: StatusIB = - [1687418943.853218][167960:167962] CHIP:DMG: { - [1687418943.853227][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418943.853233][167960:167962] CHIP:DMG: }, - [1687418943.853240][167960:167962] CHIP:DMG: - [1687418943.853246][167960:167962] CHIP:DMG: }, - [1687418943.853258][167960:167962] CHIP:DMG: - [1687418943.853264][167960:167962] CHIP:DMG: AttributeStatusIB = - [1687418943.853274][167960:167962] CHIP:DMG: { - [1687418943.853280][167960:167962] CHIP:DMG: AttributePathIB = - [1687418943.853290][167960:167962] CHIP:DMG: { - [1687418943.853296][167960:167962] CHIP:DMG: Endpoint = 0x0, - [1687418943.853304][167960:167962] CHIP:DMG: Cluster = 0x1f, - [1687418943.853311][167960:167962] CHIP:DMG: Attribute = 0x0000_0000, - [1687418943.853318][167960:167962] CHIP:DMG: ListIndex = Null, - [1687418943.853323][167960:167962] CHIP:DMG: } - [1687418943.853332][167960:167962] CHIP:DMG: - [1687418943.853338][167960:167962] CHIP:DMG: StatusIB = - [1687418943.853345][167960:167962] CHIP:DMG: { - [1687418943.853352][167960:167962] CHIP:DMG: status = 0x00 (SUCCESS), - [1687418943.853359][167960:167962] CHIP:DMG: }, - [1687418943.853368][167960:167962] CHIP:DMG: - [1687418943.853374][167960:167962] CHIP:DMG: }, - [1687418943.853383][167960:167962] CHIP:DMG: - [1687418943.853389][167960:167962] CHIP:DMG: ], - [1687418943.853405][167960:167962] CHIP:DMG: - [1687418943.853411][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418943.853418][167960:167962] CHIP:DMG: } - [1687418943.853488][167960:167962] CHIP:DMG: WriteClient moving to [AwaitingDe] - - If CR2 attempts to subscribe to an attribute on a cluster (ClusterID) for which it does not have access, the AttributePath used for the subscription would be in the form AttributePath = [[ Endpoint = EndpointID ]], but this action will be denied, and CR2 will not be able to access the attribute due to the restricted access. - - below provided the example command to subscribe to all attributes onto endpoint 0 for cluster 6 from a node id that have access to everything onto endpoint 1 - - - onoff subscribe-by-id 0xFFFFFFFF 5 100 1 0 --commissioner-nodeid 4 - [1687418974.537572][167960:167962] CHIP:EM: Rxd Ack; Removing MessageCounter:104560062 from Retrans Table on exchange 3650i - [1687418974.537610][167960:167962] CHIP:DMG: StatusResponseMessage = - [1687418974.537622][167960:167962] CHIP:DMG: { - [1687418974.537631][167960:167962] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1687418974.537640][167960:167962] CHIP:DMG: InteractionModelRevision = 1 - [1687418974.537648][167960:167962] CHIP:DMG: } - [1687418974.537658][167960:167962] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1687418974.537725][167960:167962] CHIP:EM: <<< [E:3650i S:26604 M:104560063 (Ack:37058092)] (S) Msg TX to 2:0000000000000001 [2DB4] --- Type 0001:01 (IM:StatusResponse) - [1687418974.537743][167960:167962] CHIP:IN: (S) Sending msg 104560063 on secure session with LSID: 26604 - - - With the ACL command in step-2, we are overwriting the default privilege that chip-tool has an admin. After this step-3 you need to send below mentioned command to Grant access to all clusters again. - accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode":2, "subjects":[112233,4], "targets":null}]' 1 0 - disabled: true - - - label: - "Step 6: Setup CR2 such that it does not have access to the Node. CR2 - sends a subscription request to subscribe to all attributes on all - clusters on all endpoints on a Node for which it does not have access. - AttributePath = [[ ]]." - verification: | - sending a command along with unregistered commissioner node id (5) - - any subscribe-by-id 0xFFFFFFFF 0xFFFFFFFF 10 100 1 0XFFFF --commissioner-nodeid 5 - On CR2, Verify that the DUT returns a "INVALID_ACTION" status response. - - [1695815340.162063][2522:2524] CHIP:EM: Rxd Ack; Removing MessageCounter:187875065 from Retrans Table on exchange 10455i - [1695815340.162181][2522:2524] CHIP:DMG: StatusResponseMessage = - [1695815340.162244][2522:2524] CHIP:DMG: { - [1695815340.162298][2522:2524] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1695815340.162357][2522:2524] CHIP:DMG: InteractionModelRevision = 11 - [1695815340.162412][2522:2524] CHIP:DMG: } - [1695815340.162501][2522:2524] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - disabled: true - - - label: - "Step 7: CR1 sends a subscription request action for an attribute with - an empty DataVersionFilters field. DUT sends a report data action with - the data of the attribute along with the data version. Tear down the - subscription for that attribute. Start another subscription with the - DataVersionFilter field set to the data version received above." - verification: | - Chip-Tool support required to validate this step : SDK Issue - https://github.com/project-chip/connectedhomeip/issues/28363 - - Not Testable - disabled: true - - - label: - "Step 8: CR1 sends a subscription request action for an attribute and - sets the MinIntervalFloor value to be same as MaxIntervalCeiling. - Activate the Subscription between CR1 and DUT. Modify the attribute - which has been subscribed to on the DUT." - verification: | - Please send the following command from CR1 (the subscription requester) to DUT (the device under test) to activate the subscription for the "on-time" attribute, setting the MinIntervalFloor and MaxIntervalCeiling values to be the same (in this case, 100 seconds): - - onoff subscribe on-time 100 100 1 1 --keepSubscriptions true - On the CR1(chip-tool) verify the SubscribeResponse is received successfully - [1690540281.061350][9488:9490] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0006 Attribute 0x0000_4001 DataVersion: 3310786904 - [1690540281.061363][9488:9490] CHIP:TOO: OnTime: 0 - [1690540281.061379][9488:9490] CHIP:DMG: MoveToState ReadClient[0x7faef8013880]: Moving to [AwaitingSu] - [1690540281.061427][9488:9490] CHIP:EM: <<< [E:49945i S:38251 M:151709012 (Ack:20807554)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690540281.061441][9488:9490] CHIP:IN: (S) Sending msg 151709012 on secure session with LSID: 38251 - [1690540281.061758][9488:9490] CHIP:EM: >>> [E:49945i S:38251 M:20807555 (Ack:151709012)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:04 (IM:SubscribeResponse) - [1690540281.061771][9488:9490] CHIP:EM: Found matching exchange: 49945i, Delegate: 0x7faef8013890 - [1690540281.061786][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709012 from Retrans Table on exchange 49945i - [1690540281.061800][9488:9490] CHIP:DMG: SubscribeResponse is received - [1690540281.061816][9488:9490] CHIP:DMG: SubscribeResponseMessage = - [1690540281.061825][9488:9490] CHIP:DMG: { - [1690540281.061833][9488:9490] CHIP:DMG: SubscriptionId = 0x3ef5dc34, - [1690540281.061844][9488:9490] CHIP:DMG: MaxInterval = 0x64, - [1690540281.061853][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540281.061862][9488:9490] CHIP:DMG: } - [1690540281.061875][9488:9490] CHIP:DMG: Subscription established with SubscriptionID = 0x3ef5dc34 MinInterval = 100s MaxInterval = 100s Peer = 01:0000000000000001 - - - - After activating the subscription between TH and DUT, please send the following command to modify the 'on-time' attribute value: - - >>> onoff write on-time 1 1 1 - On CR1(chip-tool), verify that the DUT sends a report data containing the current 'ontime' attribute value after the MinIntervalFloor time has elapsed - - [1690540304.761997][9488:9488] CHIP:TOO: Command: onoff write on-time 1 1 1 - [1690540304.762298][9488:9490] CHIP:TOO: Sending command to node 0x1 - [1690540304.762462][9488:9490] CHIP:CSM: FindOrEstablishSession: PeerId = [1:0000000000000001] - [1690540304.762474][9488:9490] CHIP:CSM: FindOrEstablishSession: No existing OperationalSessionSetup instance found - [1690540304.762493][9488:9490] CHIP:DIS: Found an existing secure session to [1:0000000000000001]! - [1690540304.762501][9488:9490] CHIP:DIS: OperationalSessionSetup[1:0000000000000001]: State change 1 --> 5 - [1690540304.762534][9488:9490] CHIP:TOO: cluster 0x0000_0006, attribute: 0x0000_4001, endpoint 1 - [1690540304.762585][9488:9490] CHIP:DMG: WriteClient moving to [AddAttribu] - [1690540304.762673][9488:9490] CHIP:EM: <<< [E:49946i S:38251 M:151709014] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:06 (IM:WriteRequest) - [1690540304.762693][9488:9490] CHIP:IN: (S) Sending msg 151709014 on secure session with LSID: 38251 - [1690540304.762788][9488:9490] CHIP:DMG: WriteClient moving to [AwaitingRe] - [1690540304.763448][9488:9490] CHIP:EM: >>> [E:49946i S:38251 M:20807556 (Ack:151709014)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:07 (IM:WriteResponse) - [1690540304.763464][9488:9490] CHIP:EM: Found matching exchange: 49946i, Delegate: 0x7faef800a5e0 - [1690540304.763478][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709014 from Retrans Table on exchange 49946i - [1690540304.763493][9488:9490] CHIP:DMG: WriteClient moving to [ResponseRe] - [1690540304.763518][9488:9490] CHIP:DMG: WriteResponseMessage = - [1690540304.763527][9488:9490] CHIP:DMG: { - [1690540304.763534][9488:9490] CHIP:DMG: AttributeStatusIBs = - [1690540304.763546][9488:9490] CHIP:DMG: [ - [1690540304.763553][9488:9490] CHIP:DMG: AttributeStatusIB = - [1690540304.763562][9488:9490] CHIP:DMG: { - [1690540304.763570][9488:9490] CHIP:DMG: AttributePathIB = - [1690540304.763579][9488:9490] CHIP:DMG: { - [1690540304.763589][9488:9490] CHIP:DMG: Endpoint = 0x1, - [1690540304.763597][9488:9490] CHIP:DMG: Cluster = 0x6, - [1690540304.763606][9488:9490] CHIP:DMG: Attribute = 0x0000_4001, - [1690540304.763614][9488:9490] CHIP:DMG: } - [1690540304.763626][9488:9490] CHIP:DMG: - [1690540304.763634][9488:9490] CHIP:DMG: StatusIB = - [1690540304.763646][9488:9490] CHIP:DMG: { - [1690540304.763654][9488:9490] CHIP:DMG: status = 0x00 (SUCCESS), - [1690540304.763662][9488:9490] CHIP:DMG: }, - [1690540304.763671][9488:9490] CHIP:DMG: - [1690540304.763677][9488:9490] CHIP:DMG: }, - [1690540304.763688][9488:9490] CHIP:DMG: - [1690540304.763694][9488:9490] CHIP:DMG: ], - [1690540304.763706][9488:9490] CHIP:DMG: - [1690540304.763713][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540304.763719][9488:9490] CHIP:DMG: } - [1690540304.763753][9488:9490] CHIP:DMG: WriteClient moving to [AwaitingDe] - [1690540304.763793][9488:9490] CHIP:EM: <<< [E:49946i S:38251 M:151709015 (Ack:20807556)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1690540304.763810][9488:9490] CHIP:IN: (S) Sending msg 151709015 on secure session with LSID: 38251 - [1690540304.763846][9488:9490] CHIP:EM: Flushed pending ack for MessageCounter:20807556 on exchange 49946i - [1690540325.496486][9488:9490] CHIP:EM: >>> [E:48664r S:38251 M:20807557] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:05 (IM:ReportData) - [1690540325.496520][9488:9490] CHIP:EM: Handling via exchange: 48664r, Delegate: 0x5639a50ebc68 - [1690540325.496552][9488:9490] CHIP:DMG: ReportDataMessage = - [1690540325.496565][9488:9490] CHIP:DMG: { - [1690540325.496576][9488:9490] CHIP:DMG: SubscriptionId = 0x3a11136b, - [1690540325.496587][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540325.496595][9488:9490] CHIP:DMG: } - [1690540325.496632][9488:9490] CHIP:DMG: Refresh LivenessCheckTime for 804224 milliseconds with SubscriptionId = 0x3a11136b Peer = 01:0000000000000001 - [1690540325.496682][9488:9490] CHIP:EM: <<< [E:48664r S:38251 M:151709016 (Ack:20807557)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690540325.496697][9488:9490] CHIP:IN: (S) Sending msg 151709016 on secure session with LSID: 38251 - [1690540325.497211][9488:9490] CHIP:EM: >>> [E:48664r S:38251 M:20807558 (Ack:151709016)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1690540325.497237][9488:9490] CHIP:EM: Found matching exchange: 48664r, Delegate: (nil) - [1690540325.497258][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709016 from Retrans Table on exchange 48664r - [1690540381.062201][9488:9490] CHIP:EM: >>> [E:48665r S:38251 M:20807559] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:05 (IM:ReportData) - [1690540381.062234][9488:9490] CHIP:EM: Handling via exchange: 48665r, Delegate: 0x5639a50ebc68 - [1690540381.062272][9488:9490] CHIP:DMG: ReportDataMessage = - [1690540381.062281][9488:9490] CHIP:DMG: { - [1690540381.062289][9488:9490] CHIP:DMG: SubscriptionId = 0x3ef5dc34, - [1690540381.062296][9488:9490] CHIP:DMG: AttributeReportIBs = - [1690540381.062308][9488:9490] CHIP:DMG: [ - [1690540381.062315][9488:9490] CHIP:DMG: AttributeReportIB = - [1690540381.062325][9488:9490] CHIP:DMG: { - [1690540381.062332][9488:9490] CHIP:DMG: AttributeDataIB = - [1690540381.062338][9488:9490] CHIP:DMG: { - [1690540381.062346][9488:9490] CHIP:DMG: DataVersion = 0xc5569959, - [1690540381.062354][9488:9490] CHIP:DMG: AttributePathIB = - [1690540381.062367][9488:9490] CHIP:DMG: { - [1690540381.062375][9488:9490] CHIP:DMG: Endpoint = 0x1, - [1690540381.062383][9488:9490] CHIP:DMG: Cluster = 0x6, - [1690540381.062392][9488:9490] CHIP:DMG: Attribute = 0x0000_4001, - [1690540381.062399][9488:9490] CHIP:DMG: } - [1690540381.062409][9488:9490] CHIP:DMG: - [1690540381.062417][9488:9490] CHIP:DMG: Data = 1, - [1690540381.062423][9488:9490] CHIP:DMG: }, - [1690540381.062433][9488:9490] CHIP:DMG: - [1690540381.062439][9488:9490] CHIP:DMG: }, - [1690540381.062447][9488:9490] CHIP:DMG: - [1690540381.062453][9488:9490] CHIP:DMG: ], - [1690540381.062463][9488:9490] CHIP:DMG: - [1690540381.062470][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690540381.062476][9488:9490] CHIP:DMG: } - [1690540381.062543][9488:9490] CHIP:TOO: Endpoint: 1 Cluster: 0x0000_0006 Attribute 0x0000_4001 DataVersion: 3310786905 - [1690540381.062558][9488:9490] CHIP:TOO: OnTime: 1 - [1690540381.062580][9488:9490] CHIP:DMG: Refresh LivenessCheckTime for 104224 milliseconds with SubscriptionId = 0x3ef5dc34 Peer = 01:0000000000000001 - [1690540381.062627][9488:9490] CHIP:EM: <<< [E:48665r S:38251 M:151709017 (Ack:20807559)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690540381.062641][9488:9490] CHIP:IN: (S) Sending msg 151709017 on secure session with LSID: 38251 - [1690540381.063237][9488:9490] CHIP:EM: >>> [E:48665r S:38251 M:20807560 (Ack:151709017)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0000:10 (SecureChannel:StandaloneAck) - [1690540381.063261][9488:9490] CHIP:EM: Found matching exchange: 48665r, Delegate: (nil) - [1690540381.063276][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709017 from Retrans Table on exchange 48665r - disabled: true - - - label: - "Step 9: CR1 sends a subscription request action for an attribute and - set the MinIntervalFloor value to be greater than MaxIntervalCeiling." - verification: | - Please send the following command from CR1 (the subscription requester) to DUT (the device under test) to activate the subscription for the "on-time" attribute, setting the MinIntervalFloor value to be greater than MaxIntervalCeiling: - - - onoff subscribe on-time 500 100 1 1 --keepSubscriptions true - - On CR1 (chip-tool), verify that the DUT sends an error message, confirming that the subscription is not established successfully - - [1661754615.089845][103654:103659] CHIP:DMG: StatusResponseMessage = - [1661754615.089857][103654:103659] CHIP:DMG: { - [1661754615.089868][103654:103659] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1661754615.089879][103654:103659] CHIP:DMG: InteractionModelRevision = 1 - [1661754615.089889][103654:103659] CHIP:DMG: } - [1661754615.089901][103654:103659] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1661754615.089927][103654:103659] CHIP:EM: Piggybacking Ack for MessageCounter:223396916 on exchange: 6193i - disabled: true - - - label: - "Step 10: CR1 sends a subscription request to subscribe to a specific - global attribute from all clusters on all endpoints. AttributePath = - [[Attribute = Global Attribute]]. +" - verification: | - any subscribe-by-id 0xFFFFFFFF 0xFFFD 10 300 1 0xFFFF --keepSubscriptions true - - The following log is an example of the output obtained for Attribute 0x0000_FFFD on Endpoint 0 - Pls repeat this for every cluster on every endpoint. The log represents the attributes of clusters found on different endpoints. - - Verify the presence of mandatory global attribute ClusterRevision for every cluster on every endpoint: - - - Verification Instructions: - Please use the provided example log as a guide to verify the attributes for other clusters and endpoints in a similar manner. - [1690541617.461279][9488:9490] CHIP:DMG: } - [1690541617.461374][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0003 Attribute 0x0000_FFFD DataVersion: 124546948 - [1690541617.461379][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690541617.461388][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0004 Attribute 0x0000_FFFD DataVersion: 1468663600 - [1690541617.461391][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690541617.461399][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001D Attribute 0x0000_FFFD DataVersion: 2536415407 - [1690541617.461402][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461410][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001E Attribute 0x0000_FFFD DataVersion: 1723648967 - [1690541617.461413][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461421][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_FFFD DataVersion: 659240739 - [1690541617.461424][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461432][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0028 Attribute 0x0000_FFFD DataVersion: 3950349597 - [1690541617.461435][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690541617.461443][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002A Attribute 0x0000_FFFD DataVersion: 1224601682 - [1690541617.461446][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461454][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002B Attribute 0x0000_FFFD DataVersion: 2744454868 - [1690541617.461456][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461464][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002C Attribute 0x0000_FFFD DataVersion: 463823876 - [1690541617.461467][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461475][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002D Attribute 0x0000_FFFD DataVersion: 115397017 - [1690541617.461477][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690541617.461485][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002F Attribute 0x0000_FFFD DataVersion: 85684249 - [1690541617.461488][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690541617.461496][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0030 Attribute 0x0000_FFFD DataVersion: 75615160 - [1690541617.461498][9488:9490] CHIP:TOO: ClusterRevision: 1 - disabled: true - - - label: - "Step 11: CR1 sends a subscription request to subscribe to a global - attribute on an endpoint on all clusters. AttributePath = [[Attribute - = Global Attribute, Endpoint = EndpointID ]]. +" - verification: | - any subscribe-by-id 0xFFFFFFFF 0xFFFD 10 300 1 0 --keepSubscriptions true - The following log is an example of the output obtained for Attribute 0x0000_FFFD on Endpoint 0 - Pls repeat this for every cluster on endpoint 0. The log represents the attribute of clusters found on endpoint 0. - - Verify the presence of mandatory global attribute ClusterRevision for every cluster on every endpoint: - - - Verification Instructions: - Please use the provided example log as a guide to verify the attributes for other clusters and endpoints in a similar manner. - - [1690542041.905545][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690542041.905546][9488:9490] CHIP:DMG: } - [1690542041.905621][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0003 Attribute 0x0000_FFFD DataVersion: 124546948 - [1690542041.905625][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690542041.905634][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0004 Attribute 0x0000_FFFD DataVersion: 1468663600 - [1690542041.905637][9488:9490] CHIP:TOO: ClusterRevision: 4 - [1690542041.905646][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001D Attribute 0x0000_FFFD DataVersion: 2536415407 - [1690542041.905649][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905657][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001E Attribute 0x0000_FFFD DataVersion: 1723648967 - [1690542041.905659][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905667][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_001F Attribute 0x0000_FFFD DataVersion: 659240739 - [1690542041.905670][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905678][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0028 Attribute 0x0000_FFFD DataVersion: 3950349597 - [1690542041.905680][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690542041.905688][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002A Attribute 0x0000_FFFD DataVersion: 1224601682 - [1690542041.905691][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905699][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002B Attribute 0x0000_FFFD DataVersion: 2744454868 - [1690542041.905701][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905710][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002C Attribute 0x0000_FFFD DataVersion: 463823876 - [1690542041.905712][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905720][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002D Attribute 0x0000_FFFD DataVersion: 115397017 - [1690542041.905722][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905730][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_002F Attribute 0x0000_FFFD DataVersion: 85684249 - [1690542041.905733][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690542041.905741][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0030 Attribute 0x0000_FFFD DataVersion: 75615160 - [1690542041.905743][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905751][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0031 Attribute 0x0000_FFFD DataVersion: 1962336111 - [1690542041.905753][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905761][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0032 Attribute 0x0000_FFFD DataVersion: 465381371 - [1690542041.905763][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905772][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0033 Attribute 0x0000_FFFD DataVersion: 2781452270 - [1690542041.905774][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905782][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0034 Attribute 0x0000_FFFD DataVersion: 3343308905 - [1690542041.905784][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905792][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0035 Attribute 0x0000_FFFD DataVersion: 1933667935 - [1690542041.905794][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905803][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0036 Attribute 0x0000_FFFD DataVersion: 1917440631 - [1690542041.905806][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905814][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0037 Attribute 0x0000_FFFD DataVersion: 2059544742 - [1690542041.905816][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905824][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0038 Attribute 0x0000_FFFD DataVersion: 292367345 - [1690542041.905826][9488:9490] CHIP:TOO: ClusterRevision: 2 - [1690542041.905835][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003C Attribute 0x0000_FFFD DataVersion: 4275836516 - [1690542041.905837][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905845][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003E Attribute 0x0000_FFFD DataVersion: 2334789054 - [1690542041.905848][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905856][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003F Attribute 0x0000_FFFD DataVersion: 2215403935 - [1690542041.905858][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905866][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0040 Attribute 0x0000_FFFD DataVersion: 1171006049 - [1690542041.905868][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905877][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0041 Attribute 0x0000_FFFD DataVersion: 1339481925 - [1690542041.905879][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905887][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0046 Attribute 0x0000_FFFD DataVersion: 2155717858 - [1690542041.905889][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.905897][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0x0000_0405 Attribute 0x0000_FFFD DataVersion: 2620361579 - [1690542041.906830][9488:9490] CHIP:TOO: ClusterRevision: 3 - [1690542041.906854][9488:9490] CHIP:TOO: Endpoint: 0 Cluster: 0xFFF1_FC06 Attribute 0x0000_FFFD DataVersion: 2161647034 - [1690542041.906860][9488:9490] CHIP:TOO: ClusterRevision: 1 - [1690542041.906886][9488:9490] CHIP:DMG: MoveToState ReadClient[0x7faef801d0f0]: Moving to [AwaitingSu] - [1690542041.906910][9488:9490] CHIP:EM: <<< [E:49949i S:38251 M:151709045 (Ack:20807605)] (S) Msg TX to 1:0000000000000001 [8B98] --- Type 0001:01 (IM:StatusResponse) - [1690542041.906915][9488:9490] CHIP:IN: (S) Sending msg 151709045 on secure session with LSID: 38251 - [1690542041.907098][9488:9490] CHIP:EM: >>> [E:49949i S:38251 M:20807606 (Ack:151709045)] (S) Msg RX from 1:0000000000000001 [8B98] --- Type 0001:04 (IM:SubscribeResponse) - [1690542041.907107][9488:9490] CHIP:EM: Found matching exchange: 49949i, Delegate: 0x7faef801d100 - [1690542041.907113][9488:9490] CHIP:EM: Rxd Ack; Removing MessageCounter:151709045 from Retrans Table on exchange 49949i - [1690542041.907119][9488:9490] CHIP:DMG: SubscribeResponse is received - [1690542041.907126][9488:9490] CHIP:DMG: SubscribeResponseMessage = - [1690542041.907128][9488:9490] CHIP:DMG: { - [1690542041.907131][9488:9490] CHIP:DMG: SubscriptionId = 0x9488dc04, - [1690542041.907134][9488:9490] CHIP:DMG: MaxInterval = 0x12c, - [1690542041.907137][9488:9490] CHIP:DMG: InteractionModelRevision = 1 - [1690542041.907139][9488:9490] CHIP:DMG: } - [1690542041.907144][9488:9490] CHIP:DMG: Subscription established with SubscriptionID = 0x9488dc04 MinInterval = 10s MaxInterval = 300s Peer = 01:0000000000000001 - disabled: true - - - label: - "Step 12: CR1 sends a subscription request to the DUT with both - AttributeRequests and EventRequests as empty" - verification: | - Please send the following command from TH (the subscription requester) to DUT (the device under test) to activate the subscription with both AttributeRequests and EventRequests as empty - - any subscribe-none 10 100 1 --keepSubscriptions 1 - - On CR1 (chip-tool), verify that the DUT sends an error message, confirming that the subscription is not established successfully - [1690884829.708780][84191:84193] CHIP:EM: Rxd Ack; Removing MessageCounter:136461510 from Retrans Table on exchange 23099i - [1690884829.708861][84191:84193] CHIP:DMG: StatusResponseMessage = - [1690884829.708907][84191:84193] CHIP:DMG: { - [1690884829.708947][84191:84193] CHIP:DMG: Status = 0x80 (INVALID_ACTION), - [1690884829.708988][84191:84193] CHIP:DMG: InteractionModelRevision = 1 - [1690884829.709026][84191:84193] CHIP:DMG: } - [1690884829.709064][84191:84193] CHIP:IM: Received status response, status is 0x80 (INVALID_ACTION) - [1690884829.709196][84191:84193] CHIP:EM: <<< [E:23099i S:5058 M:136461511 (Ack:90075666)] (S) Msg TX to 1:0000000000000001 [EAE3] --- Type 0001:01 (IM:StatusResponse) - [1690884829.709252][84191:84193] CHIP:IN: (S) Sending msg 136461511 on secure session with LSID: 5058 - [1690884829.709420][84191:84193] CHIP:DMG: MoveToState ReadClient[0xffff9c005e90]: Moving to [ Idle] - disabled: true diff --git a/src/app/tests/suites/manualTests.json b/src/app/tests/suites/manualTests.json index bee33964df..0e6e045b8e 100644 --- a/src/app/tests/suites/manualTests.json +++ b/src/app/tests/suites/manualTests.json @@ -124,7 +124,6 @@ "Test_TC_IDM_3_1", "Test_TC_IDM_3_2", "Test_TC_IDM_4_1", - "Test_TC_IDM_4_2", "Test_TC_IDM_4_3", "Test_TC_IDM_4_4", "Test_TC_IDM_5_1", From 4b3fff690cb7a531fe2b893d5a8a3d4e1ef683f0 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 19 Nov 2024 12:27:00 -0500 Subject: [PATCH 043/219] Handle ACL and readability in `reporting/Engine.cpp` (#36488) * Move ACL validation in reporting engine for reads * Fix up logic for ACL & return codes * Take into consideration global attributes: their ACL is ok * Make testread pass (with hacks because the test is not sane) * Update comment and model setting. * Another comment update * Fix includes * Fix typo * Restyled by clang-format * Update comment * Update ACL test logic and revert testread to original setup * Restyle * Address review comments * Restyle * Update src/app/reporting/Engine.cpp Co-authored-by: Boris Zbarsky * Update src/app/reporting/Engine.cpp Co-authored-by: Boris Zbarsky * Update src/app/reporting/Engine.cpp Co-authored-by: Boris Zbarsky * Update src/app/reporting/Engine.cpp Co-authored-by: Boris Zbarsky * Update src/app/reporting/Engine.cpp Co-authored-by: Boris Zbarsky * Restyle * Fix extra bracket --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky Co-authored-by: Andrei Litvin --- src/app/BUILD.gn | 5 +- .../CodegenDataModelProvider_Read.cpp | 27 ---- .../tests/TestCodegenModelViaMocks.cpp | 32 ----- src/app/data-model-provider/Provider.h | 10 +- src/app/reporting/Engine.cpp | 126 +++++++++++++++--- 5 files changed, 110 insertions(+), 90 deletions(-) diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 8b008c4e9b..26f9515bc1 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -201,7 +201,10 @@ static_library("interaction-model") { "reporting/reporting.h", ] - deps = [ "${chip_root}/src/app:events" ] + deps = [ + "${chip_root}/src/app:events", + "${chip_root}/src/app:global-attributes", + ] # Temporary dependency: codegen data provider instance should be provided # by the application diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp index a558b8e986..88989b5207 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Read.cpp @@ -104,33 +104,6 @@ DataModel::ActionReturnStatus CodegenDataModelProvider::ReadAttribute(const Data ChipLogValueMEI(request.path.mClusterId), request.path.mEndpointId, ChipLogValueMEI(request.path.mAttributeId), request.path.mExpanded); - // ACL check for non-internal requests - if (!request.operationFlags.Has(DataModel::OperationFlags::kInternal)) - { - VerifyOrReturnError(request.subjectDescriptor != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - Access::RequestPath requestPath{ .cluster = request.path.mClusterId, - .endpoint = request.path.mEndpointId, - .requestType = Access::RequestType::kAttributeReadRequest, - .entityId = request.path.mAttributeId }; - CHIP_ERROR err = Access::GetAccessControl().Check(*request.subjectDescriptor, requestPath, - RequiredPrivilege::ForReadAttribute(request.path)); - if (err != CHIP_NO_ERROR) - { - VerifyOrReturnError((err == CHIP_ERROR_ACCESS_DENIED) || (err == CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL), err); - - // Implementation of 8.4.3.2 of the spec for path expansion - if (request.path.mExpanded) - { - return CHIP_NO_ERROR; - } - - // access denied and access restricted have specific codes for IM - return err == CHIP_ERROR_ACCESS_DENIED ? CHIP_IM_GLOBAL_STATUS(UnsupportedAccess) - : CHIP_IM_GLOBAL_STATUS(AccessRestricted); - } - } - auto metadata = Ember::FindAttributeMetadata(request.path); // Explicit failure in finding a suitable metadata diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index 8ce369b7bd..c9b2a1b99a 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -1321,20 +1321,6 @@ TEST(TestCodegenModelViaMocks, CommandHandlerInterfaceAcceptedCommands) EXPECT_FALSE(model.GetAcceptedCommandInfo(ConcreteCommandPath(kMockEndpoint1, MockClusterId(1), 33)).has_value()); } -TEST(TestCodegenModelViaMocks, EmberAttributeReadAclDeny) -{ - UseMockNodeConfig config(gTestNodeConfig); - CodegenDataModelProviderWithContext model; - ScopedMockAccessControl accessControl; - - ReadOperation testRequest(kMockEndpoint1, MockClusterId(1), MockAttributeId(10)); - testRequest.SetSubjectDescriptor(kDenySubjectDescriptor); - - std::unique_ptr encoder = testRequest.StartEncoding(); - - ASSERT_EQ(model.ReadAttribute(testRequest.GetRequest(), *encoder), Status::UnsupportedAccess); -} - TEST(TestCodegenModelViaMocks, ReadForInvalidGlobalAttributePath) { UseMockNodeConfig config(gTestNodeConfig); @@ -1392,24 +1378,6 @@ TEST(TestCodegenModelViaMocks, EmberAttributeInvalidRead) } } -TEST(TestCodegenModelViaMocks, EmberAttributePathExpansionAccessDeniedRead) -{ - UseMockNodeConfig config(gTestNodeConfig); - CodegenDataModelProviderWithContext model; - ScopedMockAccessControl accessControl; - - ReadOperation testRequest(kMockEndpoint1, MockClusterId(1), MockAttributeId(10)); - testRequest.SetSubjectDescriptor(kDenySubjectDescriptor); - testRequest.SetPathExpanded(true); - - std::unique_ptr encoder = testRequest.StartEncoding(); - - // For expanded paths, access control failures succeed without encoding anything - // This is temporary until ACL checks are moved inside the IM/ReportEngine - ASSERT_EQ(model.ReadAttribute(testRequest.GetRequest(), *encoder), CHIP_NO_ERROR); - ASSERT_FALSE(encoder->TriedEncode()); -} - TEST(TestCodegenModelViaMocks, AccessInterfaceUnsupportedRead) { UseMockNodeConfig config(gTestNodeConfig); diff --git a/src/app/data-model-provider/Provider.h b/src/app/data-model-provider/Provider.h index 16dd7327a3..c547b75b81 100644 --- a/src/app/data-model-provider/Provider.h +++ b/src/app/data-model-provider/Provider.h @@ -60,15 +60,7 @@ class Provider : public ProviderMetadataTree virtual InteractionModelContext CurrentContext() const { return mContext; } /// TEMPORARY/TRANSITIONAL requirement for transitioning from ember-specific code - /// ReadAttribute is REQUIRED to perform: - /// - ACL validation (see notes on OperationFlags::kInternal) - /// - Validation of readability/writability (also controlled by OperationFlags::kInternal) - /// - use request.path.mExpanded to skip encoding replies for data according - /// to 8.4.3.2 of the spec: - /// > If the path indicates attribute data that is not readable, then the path SHALL - /// be discarded. - /// > Else if reading from the attribute in the path requires a privilege that is not - /// granted to access the cluster in the path, then the path SHALL be discarded. + /// ReadAttribute is REQUIRED to respond to GlobalAttribute read requests /// /// Return value notes: /// ActionReturnStatus::IsOutOfSpaceEncodingResponse diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index ea4c0014e7..63d71bfc92 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -16,17 +16,24 @@ * limitations under the License. */ +#include +#include #include #include +#include #include #include #include +#include #include #include #include #include #include +#include #include +#include +#include #include #if CHIP_CONFIG_ENABLE_ICD_SERVER @@ -52,9 +59,81 @@ Status EventPathValid(DataModel::Provider * model, const ConcreteEventPath & eve return Status::Success; } -DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, - const Access::SubjectDescriptor & subjectDescriptor, bool isFabricFiltered, - AttributeReportIBs::Builder & reportBuilder, +/// Returns the status of ACL validation. +/// If the return value has a status set, that means the ACL check failed, +/// the read must not be performed, and the returned status (which may +/// be success, when dealing with non-concrete paths) should be used +/// as the status for the read. +/// +/// If the returned value is std::nullopt, that means the ACL check passed and the +/// read should proceed. +std::optional ValidateReadAttributeACL(DataModel::Provider * dataModel, const SubjectDescriptor & subjectDescriptor, + const ConcreteReadAttributePath & path) +{ + + RequestPath requestPath{ .cluster = path.mClusterId, + .endpoint = path.mEndpointId, + .requestType = RequestType::kAttributeReadRequest, + .entityId = path.mAttributeId }; + + std::optional info = dataModel->GetAttributeInfo(path); + + // If the attribute exists, we know whether it is readable (readPrivilege has value) + // and what the required access privilege is. However for attributes missing from the metatada + // (e.g. global attributes) or completely missing attributes we do not actually know of a required + // privilege and default to kView (this is correct for global attributes and a reasonable check + // for others) + Privilege requiredPrivilege = Privilege::kView; + if (info.has_value() && info->readPrivilege.has_value()) + { + // attribute exists and is readable, set the correct read privilege + requiredPrivilege = *info->readPrivilege; + } + + CHIP_ERROR err = GetAccessControl().Check(subjectDescriptor, requestPath, requiredPrivilege); + if (err == CHIP_NO_ERROR) + { + if (IsSupportedGlobalAttributeNotInMetadata(path.mAttributeId)) + { + // Global attributes passing a kView check is ok + return std::nullopt; + } + + // We want to return "success" (i.e. nulopt) IF AND ONLY IF the attribute exists and is readable (has read privilege). + // Since the Access control check above may have passed with kView, we do another check here: + // - Attribute exists (info has value) + // - Attribute is readable (readProvilege has value) and not "write only" + // If the attribute exists and is not readable, we will return UnsupportedRead (spec 8.4.3.2: "Else if the path indicates + // attribute data that is not readable, an AttributeStatusIB SHALL be generated with the UNSUPPORTED_READ Status Code.") + // + // TODO:: https://github.com/CHIP-Specifications/connectedhomeip-spec/pull/9024 requires interleaved ordering that + // is NOT implemented here. Spec requires: + // - check cluster access check (done here as kView at least) + // - unsupported endpoint/cluster/attribute check (NOT done here) when the attribute is missing. + // this SHOULD be done here when info does not have a value. This was not done as a first pass to + // minimize amount of delta in the initial PR. + // - "write-only" attributes should return UNSUPPORTED_READ (this is done here) + if (info.has_value() && !info->readPrivilege.has_value()) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedRead); + } + + return std::nullopt; + } + VerifyOrReturnError((err == CHIP_ERROR_ACCESS_DENIED) || (err == CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL), err); + + // Implementation of 8.4.3.2 of the spec for path expansion + if (path.mExpanded) + { + return CHIP_NO_ERROR; + } + + // access denied and access restricted have specific codes for IM + return err == CHIP_ERROR_ACCESS_DENIED ? CHIP_IM_GLOBAL_STATUS(UnsupportedAccess) : CHIP_IM_GLOBAL_STATUS(AccessRestricted); +} + +DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, const SubjectDescriptor & subjectDescriptor, + bool isFabricFiltered, AttributeReportIBs::Builder & reportBuilder, const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) { ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, @@ -64,10 +143,7 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode DataModel::ReadAttributeRequest readRequest; - if (isFabricFiltered) - { - readRequest.readFlags.Set(DataModel::ReadFlags::kFabricFiltered); - } + readRequest.readFlags.Set(DataModel::ReadFlags::kFabricFiltered, isFabricFiltered); readRequest.subjectDescriptor = &subjectDescriptor; readRequest.path = path; @@ -84,9 +160,17 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode TLV::TLVWriter checkpoint; reportBuilder.Checkpoint(checkpoint); + DataModel::ActionReturnStatus status(CHIP_NO_ERROR); AttributeValueEncoder attributeValueEncoder(reportBuilder, subjectDescriptor, path, version, isFabricFiltered, encoderState); - DataModel::ActionReturnStatus status = dataModel->ReadAttribute(readRequest, attributeValueEncoder); + if (auto access_status = ValidateReadAttributeACL(dataModel, subjectDescriptor, path); access_status.has_value()) + { + status = *access_status; + } + else + { + status = dataModel->ReadAttribute(readRequest, attributeValueEncoder); + } if (status.IsSuccess()) { @@ -435,13 +519,13 @@ CHIP_ERROR Engine::CheckAccessDeniedEventPaths(TLV::TLVWriter & aWriter, bool & aHasEncodedData = true; } - Access::RequestPath requestPath{ .cluster = current->mValue.mClusterId, - .endpoint = current->mValue.mEndpointId, - .requestType = RequestType::kEventReadRequest, - .entityId = current->mValue.mEventId }; - Access::Privilege requestPrivilege = RequiredPrivilege::ForReadEvent(path); + RequestPath requestPath{ .cluster = current->mValue.mClusterId, + .endpoint = current->mValue.mEndpointId, + .requestType = RequestType::kEventReadRequest, + .entityId = current->mValue.mEventId }; + Privilege requestPrivilege = RequiredPrivilege::ForReadEvent(path); - err = Access::GetAccessControl().Check(apReadHandler->GetSubjectDescriptor(), requestPath, requestPrivilege); + err = GetAccessControl().Check(apReadHandler->GetSubjectDescriptor(), requestPath, requestPrivilege); if ((err != CHIP_ERROR_ACCESS_DENIED) && (err != CHIP_ERROR_ACCESS_RESTRICTED_BY_ARL)) { ReturnErrorOnFailure(err); @@ -580,13 +664,13 @@ CHIP_ERROR Engine::BuildSingleReportDataEventReports(ReportDataMessage::Builder CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::System::PacketBufferTLVWriter reportDataWriter; + System::PacketBufferTLVWriter reportDataWriter; ReportDataMessage::Builder reportDataBuilder; - chip::System::PacketBufferHandle bufHandle = nullptr; - uint16_t reservedSize = 0; - bool hasMoreChunks = false; - bool needCloseReadHandler = false; - size_t reportBufferMaxSize = 0; + System::PacketBufferHandle bufHandle = nullptr; + uint16_t reservedSize = 0; + bool hasMoreChunks = false; + bool needCloseReadHandler = false; + size_t reportBufferMaxSize = 0; // Reserved size for the MoreChunks boolean flag, which takes up 1 byte for the control tag and 1 byte for the context tag. const uint32_t kReservedSizeForMoreChunksFlag = 1 + 1; @@ -623,7 +707,7 @@ CHIP_ERROR Engine::BuildAndSendSingleReportData(ReadHandler * apReadHandler) // Always limit the size of the generated packet to fit within the max size returned by the ReadHandler regardless // of the available buffer capacity. // Also, we need to reserve some extra space for the MIC field. - reportDataWriter.ReserveBuffer(static_cast(reservedSize + chip::Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); + reportDataWriter.ReserveBuffer(static_cast(reservedSize + Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES)); // Create a report data. err = reportDataBuilder.Init(&reportDataWriter); From 96c601d51d548bd7ab13a8432a7451fc31c6370d Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Tue, 19 Nov 2024 21:39:41 +0200 Subject: [PATCH 044/219] [Telink] Update Docker image (Zephyr update) (#36563) --- integrations/docker/images/base/chip-build/version | 2 +- integrations/docker/images/stage-2/chip-build-telink/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/docker/images/base/chip-build/version b/integrations/docker/images/base/chip-build/version index 6df5517b7e..29c26fda8e 100644 --- a/integrations/docker/images/base/chip-build/version +++ b/integrations/docker/images/base/chip-build/version @@ -1 +1 @@ -92 : [Telink] Update Docker image (Zephyr update) +93 : [Telink] Update Docker image (Zephyr update) diff --git a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile index b286bb8a74..e028e0b9f6 100644 --- a/integrations/docker/images/stage-2/chip-build-telink/Dockerfile +++ b/integrations/docker/images/stage-2/chip-build-telink/Dockerfile @@ -18,7 +18,7 @@ RUN set -x \ && : # last line # Setup Zephyr -ARG ZEPHYR_REVISION=d88a47760dd4c7e57dfcc83e7c5856a9cea88fc1 +ARG ZEPHYR_REVISION=8b29ee6b118ebe6eeec3224dbe343474e11403d8 WORKDIR /opt/telink/zephyrproject RUN set -x \ && python3 -m pip install --break-system-packages -U --no-cache-dir west \ From 918f11eae7b6dae31c88108d327d7dfbd4cd189f Mon Sep 17 00:00:00 2001 From: Marius Tache <102153746+marius-alex-tache@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:39:50 +0200 Subject: [PATCH 045/219] [nxp][platform][k32w0] Remove KVS logs for init phase (#36553) * [nxp][platform][k32w0] Remove KVS logs for init phase Signed-off-by: marius-alex-tache * Restyled by whitespace --------- Signed-off-by: marius-alex-tache Co-authored-by: Restyled.io --- .../nxp/k32w0/KeyValueStoreManagerImpl.cpp | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp index 34666e491a..0ba86d0c4b 100644 --- a/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp +++ b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp @@ -130,35 +130,19 @@ CHIP_ERROR KeyValueStoreManagerImpl::Init() CHIP_ERROR err = CHIP_NO_ERROR; err = sKeysStorage.Init(Internal::RamStorage::kRamBufferInitialSize); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS keys storage with id: %d. Error: %s", kNvmId_KvsKeys, ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sValuesStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS values storage with id: %d. Error: %s", kNvmId_KvsValues, ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sSubscriptionStorage.Init(Internal::RamStorage::kRamBufferInitialSize); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS subscription storage with id: %d. Error: %s", kNvmId_KvsSubscription, - ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sGroupsStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS groups storage with id: %d. Error: %s", kNvmId_KvsGroups, ErrorStr(err)); - } + ReturnErrorOnFailure(err); err = sAclStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(DeviceLayer, "Cannot init KVS acl storage with id: %d. Error: %s", kNvmId_KvsAcl, ErrorStr(err)); - } + ReturnErrorOnFailure(err); #if CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE ChipLogProgress(DeviceLayer, "Moving some keys to dedicated storage"); From 6012d99df00870d9a262eed1dbf54fa3e3660fe3 Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Wed, 20 Nov 2024 01:11:24 +0530 Subject: [PATCH 046/219] setup: support installations with Python3.13 (#36549) --- scripts/setup/constraints.txt | 2 -- scripts/setup/requirements.all.txt | 2 ++ scripts/tools/telink/requirements.txt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/setup/constraints.txt b/scripts/setup/constraints.txt index 1b52443141..874d46f6f1 100644 --- a/scripts/setup/constraints.txt +++ b/scripts/setup/constraints.txt @@ -32,8 +32,6 @@ cbor2==5.4.6 # via -r requirements.zephyr.txt certifi==2022.12.7 # via requests -cffi==1.15.1 - # via cryptography charset-normalizer==3.0.1 # via requests click==8.1.3 diff --git a/scripts/setup/requirements.all.txt b/scripts/setup/requirements.all.txt index 346abfa393..4a7672a08f 100644 --- a/scripts/setup/requirements.all.txt +++ b/scripts/setup/requirements.all.txt @@ -43,6 +43,8 @@ mypy-protobuf==3.5.0 protobuf==4.24.4 types-protobuf==4.24.0.2 +cffi==1.15.0; python_version < "3.13" +cffi==1.17.1; python_version >= "3.13" cryptography # python unit tests diff --git a/scripts/tools/telink/requirements.txt b/scripts/tools/telink/requirements.txt index 58b519dc92..e76b1423e4 100644 --- a/scripts/tools/telink/requirements.txt +++ b/scripts/tools/telink/requirements.txt @@ -1,5 +1,6 @@ cryptography==43.0.1 -cffi==1.15.0 +cffi==1.15.0; python_version < "3.13" +cffi==1.17.1; python_version >= "3.13" future==0.18.3 pycparser==2.21 pypng==0.0.21 From db9d87267e20f535bb20c814f54c88c4a56909ba Mon Sep 17 00:00:00 2001 From: Marius Preda Date: Tue, 19 Nov 2024 21:45:12 +0200 Subject: [PATCH 047/219] [NXP][third_party] Fixed memory leak in BR mDNS code (#36543) * [NXP][third_party] Fixed memory leak in BR mDNS code This commit fixes potential memory leaks that could happen if multiple resolve of browse operations are done without calling the appropriate stop function to clean up the allocated resources. If using the Matter CLI this issue is not possible as the CLI always stops the previous operation but other processes calling the resolve/browse API might not follow this flow. Also fixed the return value of the StopBrowse function. Signed-off-by: Marius Preda * Restyled by clang-format --------- Signed-off-by: Marius Preda Co-authored-by: Restyled.io --- src/platform/nxp/common/DnssdImpl.cpp | 4 ++-- src/platform/nxp/common/DnssdImplBr.cpp | 27 +++++++++++++++++++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/platform/nxp/common/DnssdImpl.cpp b/src/platform/nxp/common/DnssdImpl.cpp index 5b35693534..65061aa80c 100644 --- a/src/platform/nxp/common/DnssdImpl.cpp +++ b/src/platform/nxp/common/DnssdImpl.cpp @@ -99,7 +99,7 @@ CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chi chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context, intptr_t * browseIdentifier) { - if (ConnectivityMgr().IsWiFiStationConnected()) //|| ESP32Utils::HasIPv6LinkLocalAddress(ESP32Utils::kDefaultEthernetNetifKey)) + if (ConnectivityMgr().IsWiFiStationConnected()) { ReturnErrorOnFailure(NxpChipDnssdBrowse(type, protocol, addressType, interface, callback, context, browseIdentifier)); } @@ -119,7 +119,7 @@ CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier) CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback, void * context) { - if (ConnectivityMgr().IsWiFiStationConnected()) //|| ESP32Utils::HasIPv6LinkLocalAddress(ESP32Utils::kDefaultEthernetNetifKey)) + if (ConnectivityMgr().IsWiFiStationConnected()) { ReturnErrorOnFailure(NxpChipDnssdResolve(service, interface, callback, context)); } diff --git a/src/platform/nxp/common/DnssdImplBr.cpp b/src/platform/nxp/common/DnssdImplBr.cpp index 5eab86fe19..e65ae2d5ef 100644 --- a/src/platform/nxp/common/DnssdImplBr.cpp +++ b/src/platform/nxp/common/DnssdImplBr.cpp @@ -28,6 +28,8 @@ #include #include +#include + using namespace ::chip::DeviceLayer; using namespace chip::DeviceLayer::Internal; @@ -363,6 +365,11 @@ CHIP_ERROR NxpChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, if (type == nullptr || callback == nullptr) return CHIP_ERROR_INVALID_ARGUMENT; + if (mBrowseContext != nullptr) + { + NxpChipDnssdStopBrowse(reinterpret_cast(mBrowseContext)); + } + mBrowseContext = Platform::New(context, callback); VerifyOrReturnError(mBrowseContext != nullptr, CHIP_ERROR_NO_MEMORY); @@ -412,7 +419,8 @@ CHIP_ERROR NxpChipDnssdStopBrowse(intptr_t browseIdentifier) // that has been freed in DispatchBrowseEmpty. if ((true == bBrowseInProgress) && (browseContext)) { - browseContext->error = MapOpenThreadError(otMdnsStopBrowser(thrInstancePtr, &browseContext->mBrowseInfo)); + error = otMdnsStopBrowser(thrInstancePtr, &browseContext->mBrowseInfo); + browseContext->error = MapOpenThreadError(error); // browse context will be freed in DispatchBrowseEmpty DispatchBrowseEmpty(reinterpret_cast(browseContext)); @@ -430,6 +438,13 @@ CHIP_ERROR NxpChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId in otInstance * thrInstancePtr = ThreadStackMgrImpl().OTInstance(); + if (mResolveContext != nullptr) + { + // In case there is an ongoing query and NxpChipDnssdResolveNoLongerNeeded has not been called yet + // free the allocated context and do a proper cleanup of the previous transaction + NxpChipDnssdResolveNoLongerNeeded(mResolveContext->mMdnsService.mName); + } + mResolveContext = Platform::New(context, callback); VerifyOrReturnError(mResolveContext != nullptr, CHIP_ERROR_NO_MEMORY); @@ -450,12 +465,16 @@ CHIP_ERROR NxpChipDnssdResolve(DnssdService * browseResult, Inet::InterfaceId in mResolveContext->mSrvInfo.mServiceInstance = mResolveContext->mMdnsService.mName; mResolveContext->mSrvInfo.mServiceType = mResolveContext->mServiceType; - return MapOpenThreadError(otMdnsStartSrvResolver(thrInstancePtr, &mResolveContext->mSrvInfo)); + error = MapOpenThreadError(otMdnsStartSrvResolver(thrInstancePtr, &mResolveContext->mSrvInfo)); } - else + + if (error != CHIP_NO_ERROR) { - return error; + Platform::Delete(mResolveContext); + mResolveContext = nullptr; } + + return error; } void NxpChipDnssdResolveNoLongerNeeded(const char * instanceName) { From c39a06fe99ec09f10c1702eece90d98aab94ea4f Mon Sep 17 00:00:00 2001 From: Pg Date: Tue, 19 Nov 2024 20:46:51 +0100 Subject: [PATCH 048/219] Delete user and group in case of conflicts (#36528) --- .devcontainer/Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3d2c6295f8..d3c222df06 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -40,7 +40,11 @@ RUN apt-get update \ icecc \ && : -RUN groupadd -g $USER_GID $USERNAME \ +RUN (getent passwd $USER_UID && userdel -f $(getent passwd $USER_UID | cut -d: -f1) || true) \ + && (getent group $USER_GID && groupdel -f $(getent group $USER_GID | cut -d: -f1) || true) \ + && (getent passwd $USERNAME && userdel -f $USERNAME || true) \ + && (getent group $USERNAME && groupdel -f $USERNAME || true) \ + && groupadd -g $USER_GID $USERNAME \ && useradd --no-log-init -s /bin/bash -u $USER_UID -g $USER_GID -G docker,sudo -m $USERNAME \ && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ && chmod 0440 /etc/sudoers.d/$USERNAME \ From ba33cf29a0c0bba5c0b5f34e992d2541c420af9f Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Tue, 19 Nov 2024 11:49:29 -0800 Subject: [PATCH 049/219] [Fabric-Sync] Implement pair-device command (#36508) * [Fabric-Sync] Port pair-device command from fabric-admin * Update examples/fabric-sync/shell/ShellCommands.cpp Co-authored-by: Terence Hampson --------- Co-authored-by: Terence Hampson --- examples/fabric-sync/shell/BUILD.gn | 2 + .../fabric-sync/shell/PairDeviceCommand.cpp | 79 +++++++++++++++++++ .../fabric-sync/shell/PairDeviceCommand.h | 38 +++++++++ examples/fabric-sync/shell/ShellCommands.cpp | 36 +++++++++ 4 files changed, 155 insertions(+) create mode 100644 examples/fabric-sync/shell/PairDeviceCommand.cpp create mode 100644 examples/fabric-sync/shell/PairDeviceCommand.h diff --git a/examples/fabric-sync/shell/BUILD.gn b/examples/fabric-sync/shell/BUILD.gn index 3aa5612225..d5545087c9 100644 --- a/examples/fabric-sync/shell/BUILD.gn +++ b/examples/fabric-sync/shell/BUILD.gn @@ -33,6 +33,8 @@ source_set("shell") { "AddDeviceCommand.h", "CommandRegistry.cpp", "CommandRegistry.h", + "PairDeviceCommand.cpp", + "PairDeviceCommand.h", "RemoveBridgeCommand.cpp", "RemoveBridgeCommand.h", "RemoveDeviceCommand.cpp", diff --git a/examples/fabric-sync/shell/PairDeviceCommand.cpp b/examples/fabric-sync/shell/PairDeviceCommand.cpp new file mode 100644 index 0000000000..796c062a2d --- /dev/null +++ b/examples/fabric-sync/shell/PairDeviceCommand.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "PairDeviceCommand.h" + +#include +#include + +using namespace ::chip; + +namespace commands { + +PairDeviceCommand::PairDeviceCommand(chip::NodeId nodeId, const char * payload) : mNodeId(nodeId), mPayload(payload) {} + +void PairDeviceCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) +{ + if (mNodeId != deviceId) + { + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to pair non-specified device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + else + { + ChipLogProgress(NotSpecified, "Commissioning complete for non-specified device: NodeId: " ChipLogFormatX64, + ChipLogValueX64(deviceId)); + } + return; + } + + if (err == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Successfully paired device: NodeId: " ChipLogFormatX64, ChipLogValueX64(mNodeId)); + + admin::DeviceManager::Instance().UpdateLastUsedNodeId(mNodeId); + } + else + { + ChipLogError(NotSpecified, "Failed to pair device (0x:" ChipLogFormatX64 ") with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(deviceId), err.Format()); + } + + CommandRegistry::Instance().ResetActiveCommand(); +} + +CHIP_ERROR PairDeviceCommand::RunCommand() +{ + if (admin::DeviceManager::Instance().IsCurrentBridgeDevice(mNodeId)) + { + // print to console + fprintf(stderr, "The specified node ID has been reserved by the Fabric Bridge.\n"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + ChipLogProgress(NotSpecified, "Running PairDeviceCommand with Node ID: %lu, Code: %s", mNodeId, mPayload); + + admin::PairingManager::Instance().SetPairingDelegate(this); + + return admin::PairingManager::Instance().PairDeviceWithCode(mNodeId, mPayload); +} + +} // namespace commands diff --git a/examples/fabric-sync/shell/PairDeviceCommand.h b/examples/fabric-sync/shell/PairDeviceCommand.h new file mode 100644 index 0000000000..d917b5103f --- /dev/null +++ b/examples/fabric-sync/shell/PairDeviceCommand.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include +#include + +namespace commands { + +class PairDeviceCommand : public Command, public admin::PairingDelegate +{ +public: + PairDeviceCommand(chip::NodeId nodeId, const char * payload); + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; + CHIP_ERROR RunCommand() override; + +private: + chip::NodeId mNodeId; + const char * mPayload; +}; + +} // namespace commands diff --git a/examples/fabric-sync/shell/ShellCommands.cpp b/examples/fabric-sync/shell/ShellCommands.cpp index 4923823481..f117e9c7b9 100644 --- a/examples/fabric-sync/shell/ShellCommands.cpp +++ b/examples/fabric-sync/shell/ShellCommands.cpp @@ -17,6 +17,7 @@ #include "ShellCommands.h" #include "AddBridgeCommand.h" #include "AddDeviceCommand.h" +#include "PairDeviceCommand.h" #include "RemoveBridgeCommand.h" #include "RemoveDeviceCommand.h" #include "SyncDeviceCommand.h" @@ -46,6 +47,7 @@ static CHIP_ERROR PrintAllCommands() streamer_printf(sout, " add-device Pair a device to local fabric. Usage: app add-device node-id setup-pin-code " "device-remote-ip device-remote-port\r\n"); + streamer_printf(sout, " pair-device Pair a device to local fabric. Usage: app pair-device node-id code\r\n"); streamer_printf(sout, " remove-device Remove a device from the local fabric. Usage: app remove-device node-id\r\n"); streamer_printf(sout, " sync-device Sync a device from other ecosystem. Usage: app sync-device endpointid\r\n"); streamer_printf(sout, "\r\n"); @@ -145,6 +147,36 @@ static CHIP_ERROR HandleAddDeviceCommand(int argc, char ** argv) return result; } +static CHIP_ERROR HandlePairDeviceCommand(int argc, char ** argv) +{ + if (argc != 3) + { + fprintf(stderr, "Invalid arguments. Usage: app pair-device node-id code\n"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Check if there is already an active command + if (commands::CommandRegistry::Instance().IsCommandActive()) + { + fprintf(stderr, "Another command is currently active. Please wait until it completes.\n"); + return CHIP_ERROR_BUSY; + } + + // Parse arguments + chip::NodeId nodeId = static_cast(strtoull(argv[1], nullptr, 10)); + const char * setUpCode = argv[2]; + + auto command = std::make_unique(nodeId, setUpCode); + + CHIP_ERROR result = command->RunCommand(); + if (result == CHIP_NO_ERROR) + { + commands::CommandRegistry::Instance().SetActiveCommand(std::move(command)); + } + + return result; +} + static CHIP_ERROR HandleRemoveDeviceCommand(int argc, char ** argv) { if (argc != 2) @@ -227,6 +259,10 @@ static CHIP_ERROR AppPlatformHandler(int argc, char ** argv) { return HandleAddDeviceCommand(argc, argv); } + else if (strcmp(argv[0], "pair-device") == 0) + { + return HandlePairDeviceCommand(argc, argv); + } else if (strcmp(argv[0], "remove-device") == 0) { return HandleRemoveDeviceCommand(argc, argv); From 368cf2e417fa19c1637a8a830a4c4fa5920712d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Tue, 19 Nov 2024 20:49:49 +0100 Subject: [PATCH 050/219] Fix cluster Bridged Device Basic Information in matter-devices.xml (#36467) --- src/app/zap-templates/zcl/data-model/chip/matter-devices.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml index 54fe73d5f0..3e95a2de48 100644 --- a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml +++ b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml @@ -203,7 +203,7 @@ limitations under the License. CLIENT_LIST PARTS_LIST - + REACHABLE From 61121b8484b60271b41f92059be23d54affeb132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Tue, 19 Nov 2024 20:50:17 +0100 Subject: [PATCH 051/219] Fixes Carbon Monoxide Concentration Measurement in matter-devices.xml (#36466) Fixes Carbon Monoxide Concentration Measurement in matter-devices.xml --- src/app/zap-templates/zcl/data-model/chip/matter-devices.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml index 3e95a2de48..84b5720e16 100644 --- a/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml +++ b/src/app/zap-templates/zcl/data-model/chip/matter-devices.xml @@ -2069,7 +2069,7 @@ limitations under the License. - + From 83b75e1711cd7f5cc21d2780c1a9aa8a2a0e24fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Tue, 19 Nov 2024 21:46:39 +0100 Subject: [PATCH 052/219] [Silabs] Replace rvc by dishwasher in SL example (#36367) * Replace rvc by dishwasher Replace rvc by dishwasher * Restyle --- .../silabs/include/operational-state-delegate-impl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h b/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h index 8b8d24e115..354dea9912 100644 --- a/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h +++ b/examples/dishwasher-app/silabs/include/operational-state-delegate-impl.h @@ -67,7 +67,7 @@ class OperationalStateDelegate : public Delegate void SetEndpointId(EndpointId endpointId); private: - const GenericOperationalState rvcOpStateList[4] = { + const GenericOperationalState dishwasherOpStateList[4] = { GenericOperationalState(to_underlying(OperationalStateEnum::kStopped)), GenericOperationalState(to_underlying(OperationalStateEnum::kRunning)), GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)), @@ -76,7 +76,8 @@ class OperationalStateDelegate : public Delegate EndpointId mEndpointId; - DataModel::List mOperationalStateList = Span(rvcOpStateList); + DataModel::List mOperationalStateList = + Span(dishwasherOpStateList); const Span mOperationalPhaseList; }; From e19ac8581f88c5ca0db13dfe854782888d9e6e8f Mon Sep 17 00:00:00 2001 From: pankore <86098180+pankore@users.noreply.github.com> Date: Wed, 20 Nov 2024 06:41:15 +0800 Subject: [PATCH 053/219] [ameba] Ameba SNTP and observer support (#36382) * [ameba] Support Time Syncronization Using SNTP * [ameba] Synchronize RTC with SNTP * [ameba] Add CONFIG_ENABLE_AMEBA_SNTP to config/ameba/chip.cmake and run restyle-diff.sh * [ameba] Add Ameba Observer for Ameba Examples * [Ameba] Fix build with all-clusters-minimal-app and SystemTimeSupport.cpp * [Ameba] Update Docker Version to 91 * [Ameba] moved AmebaObserver.h to examples/platform/ameba/observer/ and updated Ameba cmake * [Ameba] simplified #if defined(CONFIG_ENABLE_AMEBA_SNTP) && (CONFIG_ENABLE_AMEBA_SNTP == 1) to #if CONFIG_ENABLE_AMEBA_SNTP --------- Co-authored-by: Andrei Litvin --- config/ameba/chip.cmake | 1 + .../air-purifier-app/ameba/chip_main.cmake | 6 +++ .../ameba/main/chipinterface.cpp | 4 ++ .../all-clusters-app/ameba/chip_main.cmake | 1 + .../ameba/chip_main.cmake | 7 +-- .../ameba/main/chipinterface.cpp | 4 ++ examples/chef/ameba/chip_main.cmake | 1 + examples/chef/ameba/main/chipinterface.cpp | 4 ++ .../light-switch-app/ameba/chip_main.cmake | 1 + .../ameba/main/chipinterface.cpp | 4 ++ examples/lighting-app/ameba/chip_main.cmake | 1 + .../lighting-app/ameba/main/chipinterface.cpp | 4 ++ .../ota-requestor-app/ameba/chip_main.cmake | 1 + .../ameba/main/chipinterface.cpp | 4 ++ .../ameba/observer}/AmebaObserver.h | 0 src/platform/Ameba/SystemTimeSupport.cpp | 45 ++++++++++++------- 16 files changed, 69 insertions(+), 19 deletions(-) rename examples/{all-clusters-app/ameba/main/include => platform/ameba/observer}/AmebaObserver.h (100%) diff --git a/config/ameba/chip.cmake b/config/ameba/chip.cmake index 47444055f6..9cd2ab5511 100644 --- a/config/ameba/chip.cmake +++ b/config/ameba/chip.cmake @@ -32,6 +32,7 @@ list( -DMBEDTLS_CONFIG_FILE= -D_POSIX_REALTIME_SIGNALS -DCHIP_SHELL_MAX_TOKENS=11 + -DCONFIG_ENABLE_AMEBA_SNTP=1 ) list( diff --git a/examples/air-purifier-app/ameba/chip_main.cmake b/examples/air-purifier-app/ameba/chip_main.cmake index 22a325bf6e..4811bda0d8 100755 --- a/examples/air-purifier-app/ameba/chip_main.cmake +++ b/examples/air-purifier-app/ameba/chip_main.cmake @@ -145,6 +145,11 @@ endif (matter_enable_ota_requestor) list( APPEND ${list_chip_main_sources} + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/air-purifier-manager.cpp + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/air-quality-sensor-manager.cpp + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/filter-delegates.cpp + ${chip_dir}/examples/air-purifier-app/air-purifier-common/src/thermostat-manager.cpp + ${chip_dir}/examples/air-purifier-app/ameba/main/chipinterface.cpp ${chip_dir}/examples/air-purifier-app/ameba/main/DeviceCallbacks.cpp ${chip_dir}/examples/air-purifier-app/ameba/main/CHIPDeviceManager.cpp @@ -192,6 +197,7 @@ target_include_directories( ${chip_dir}/examples/air-purifier-app/air-purifier-common/include ${chip_dir}/examples/air-purifier-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/air-purifier-app/ameba/main/chipinterface.cpp b/examples/air-purifier-app/ameba/main/chipinterface.cpp index 0829bb041e..34653db482 100644 --- a/examples/air-purifier-app/ameba/main/chipinterface.cpp +++ b/examples/air-purifier-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Server.h" @@ -139,6 +140,8 @@ static void InitServer(intptr_t context) VerifyOrDie((sAmebaPersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -151,6 +154,7 @@ static void InitServer(intptr_t context) PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); InitAirPurifierManager(); } diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 852673d07d..cdcaab1565 100644 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -248,6 +248,7 @@ target_include_directories( ${chip_dir}/examples/energy-management-app/energy-management-common/energy-reporting/include ${chip_dir}/examples/all-clusters-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/platform/ameba/route_hook ${chip_dir}/examples/providers ${chip_dir_output}/gen/include diff --git a/examples/all-clusters-minimal-app/ameba/chip_main.cmake b/examples/all-clusters-minimal-app/ameba/chip_main.cmake index a2d1e364d6..d60f4f5899 100755 --- a/examples/all-clusters-minimal-app/ameba/chip_main.cmake +++ b/examples/all-clusters-minimal-app/ameba/chip_main.cmake @@ -128,9 +128,9 @@ endif (matter_enable_ota_requestor) list( APPEND ${list_chip_main_sources} - ${chip_dir}/examples/all-clusters-minimal-app/all-clusters-common/src/bridged-actions-stub.cpp - ${chip_dir}/examples/all-clusters-minimal-app/all-clusters-common/src/smco-stub.cpp - ${chip_dir}/examples/all-clusters-minimal-app/all-clusters-common/src/static-supported-modes-manager.cpp + ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp + ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp + ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp ${chip_dir}/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp ${chip_dir}/examples/all-clusters-minimal-app/ameba/main/DeviceCallbacks.cpp @@ -176,6 +176,7 @@ target_include_directories( ${chip_dir}/examples/all-clusters-app/all-clusters-common ${chip_dir}/examples/all-clusters-app/all-clusters-common/include ${chip_dir}/examples/all-clusters-minimal-app/ameba/main/include + ${chip_dir}/examples/platform/ameba/observer ${chip_dir_output}/gen/include ${chip_dir}/src/include/ ${chip_dir}/src/lib/ diff --git a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp index 61f7db147f..1fedda9583 100644 --- a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Globals.h" @@ -157,6 +158,8 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); // Initialize device attestation config @@ -173,6 +176,7 @@ static void InitServer(intptr_t context) PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } Clusters::ModeSelect::setSupportedModesManager(&sStaticSupportedModesManager); + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/chef/ameba/chip_main.cmake b/examples/chef/ameba/chip_main.cmake index 87c8aa158d..cea3b85b4f 100755 --- a/examples/chef/ameba/chip_main.cmake +++ b/examples/chef/ameba/chip_main.cmake @@ -66,6 +66,7 @@ target_include_directories( ${chip_dir}/examples/all-clusters-app/all-clusters-common/include ${chip_dir}/examples/all-clusters-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/chef/ameba/main/chipinterface.cpp b/examples/chef/ameba/main/chipinterface.cpp index f747cbbd88..ccdf43f3e5 100644 --- a/examples/chef/ameba/main/chipinterface.cpp +++ b/examples/chef/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Globals.h" @@ -104,6 +105,8 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -115,6 +118,7 @@ static void InitServer(intptr_t context) // QR code will be used with CHIP Tool PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/light-switch-app/ameba/chip_main.cmake b/examples/light-switch-app/ameba/chip_main.cmake index 629c423c0f..800f51a704 100755 --- a/examples/light-switch-app/ameba/chip_main.cmake +++ b/examples/light-switch-app/ameba/chip_main.cmake @@ -201,6 +201,7 @@ target_include_directories( ${chip_dir}/zzz_generated/app-common ${chip_dir}/examples/light-switch-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/light-switch-app/ameba/main/chipinterface.cpp b/examples/light-switch-app/ameba/main/chipinterface.cpp index 35d11da634..31f285db45 100644 --- a/examples/light-switch-app/ameba/main/chipinterface.cpp +++ b/examples/light-switch-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "BindingHandler.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" @@ -109,6 +110,8 @@ static void InitServer(intptr_t context) VerifyOrDie((sAmebaPersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -124,6 +127,7 @@ static void InitServer(intptr_t context) #if CONFIG_ENABLE_CHIP_SHELL InitBindingHandler(); #endif + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/lighting-app/ameba/chip_main.cmake b/examples/lighting-app/ameba/chip_main.cmake index 11590553cf..f8f1c6b158 100755 --- a/examples/lighting-app/ameba/chip_main.cmake +++ b/examples/lighting-app/ameba/chip_main.cmake @@ -196,6 +196,7 @@ target_include_directories( ${chip_dir}/examples/lighting-app/lighting-common/include ${chip_dir}/examples/lighting-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${chip_dir_output}/gen/include ${chip_dir}/src/include/ diff --git a/examples/lighting-app/ameba/main/chipinterface.cpp b/examples/lighting-app/ameba/main/chipinterface.cpp index 76459b728a..d034fe0c1c 100644 --- a/examples/lighting-app/ameba/main/chipinterface.cpp +++ b/examples/lighting-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "Globals.h" @@ -129,6 +130,8 @@ static void InitServer(intptr_t context) VerifyOrDie((sAmebaPersistentStorageOpKeystore.Init(initParams.persistentStorageDelegate)) == CHIP_NO_ERROR); initParams.operationalKeystore = &sAmebaPersistentStorageOpKeystore; #endif + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -140,6 +143,7 @@ static void InitServer(intptr_t context) // QR code will be used with CHIP Tool PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE)); } + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/ota-requestor-app/ameba/chip_main.cmake b/examples/ota-requestor-app/ameba/chip_main.cmake index 28b2fb5d20..bc9b41c8fb 100644 --- a/examples/ota-requestor-app/ameba/chip_main.cmake +++ b/examples/ota-requestor-app/ameba/chip_main.cmake @@ -62,6 +62,7 @@ target_include_directories( ${chip_dir}/src/app/clusters/ota-requestor ${chip_dir}/examples/ota-requestor-app/ameba/main/include ${chip_dir}/examples/platform/ameba + ${chip_dir}/examples/platform/ameba/observer ${chip_dir}/examples/providers ${sdk_root}/component/soc/realtek/amebad/fwlib/include ) diff --git a/examples/ota-requestor-app/ameba/main/chipinterface.cpp b/examples/ota-requestor-app/ameba/main/chipinterface.cpp index dfac5c97f2..6d0af83d5c 100644 --- a/examples/ota-requestor-app/ameba/main/chipinterface.cpp +++ b/examples/ota-requestor-app/ameba/main/chipinterface.cpp @@ -17,6 +17,7 @@ #include +#include "AmebaObserver.h" #include "CHIPDeviceManager.h" #include "DeviceCallbacks.h" #include "chip_porting.h" @@ -76,11 +77,14 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + static AmebaObserver sAmebaObserver; + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); NetWorkCommissioningInstInit(); + chip::Server::GetInstance().GetFabricTable().AddFabricDelegate(&sAmebaObserver); } extern "C" void ChipTest(void) diff --git a/examples/all-clusters-app/ameba/main/include/AmebaObserver.h b/examples/platform/ameba/observer/AmebaObserver.h similarity index 100% rename from examples/all-clusters-app/ameba/main/include/AmebaObserver.h rename to examples/platform/ameba/observer/AmebaObserver.h diff --git a/src/platform/Ameba/SystemTimeSupport.cpp b/src/platform/Ameba/SystemTimeSupport.cpp index acf451d498..8a5f59131d 100644 --- a/src/platform/Ameba/SystemTimeSupport.cpp +++ b/src/platform/Ameba/SystemTimeSupport.cpp @@ -58,26 +58,32 @@ Milliseconds64 ClockImpl::GetMonotonicMilliseconds64(void) CHIP_ERROR ClockImpl::GetClock_RealTime(Clock::Microseconds64 & curTime) { - // TODO(19081): This platform does not properly error out if wall clock has - // not been set. For now, short circuit this. - return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; -#if 0 - time_t seconds; - struct rtkTimeVal tv; +#if CONFIG_ENABLE_AMEBA_SNTP + time_t seconds = 0, uSeconds = 0; - seconds = matter_rtc_read(); - - tv.tv_sec = (uint32_t) seconds; - tv.tv_usec = 0; + if (matter_sntp_rtc_is_sync()) // if RTC is already sync with SNTP, read directly from RTC + { + seconds = matter_rtc_read(); // ameba rtc precission is in seconds only + } + else // read from SNTP and sync RTC with SNTP + { + matter_sntp_get_current_time(&seconds, &uSeconds); + } - if (tv.tv_sec < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) + if (seconds < CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) { return CHIP_ERROR_REAL_TIME_NOT_SYNCED; } - static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative tv_sec values!"); - curTime = Microseconds64((static_cast(tv.tv_sec) * UINT64_C(1000000)) + static_cast(tv.tv_usec)); + if (uSeconds < 0) + { + return CHIP_ERROR_REAL_TIME_NOT_SYNCED; + } + static_assert(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD >= 0, "We might be letting through negative uSeconds values!"); + curTime = Microseconds64((static_cast(seconds) * UINT64_C(1000000)) + static_cast(uSeconds)); return CHIP_NO_ERROR; +#else + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; #endif } @@ -105,9 +111,16 @@ CHIP_ERROR InitClock_RealTime() Clock::Microseconds64((static_cast(CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) * UINT64_C(1000000))); // Use CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD as the initial value of RealTime. // Then the RealTime obtained from GetClock_RealTime will be always valid. - // - // TODO(19081): This is broken because it causes the platform to report - // that it does have wall clock time when it actually doesn't. +#if CONFIG_ENABLE_AMEBA_SNTP + time_t seconds = 0, uSeconds = 0; + + matter_sntp_init(); + matter_sntp_get_current_time(&seconds, &uSeconds); // try to read from SNTP and sync RTC with SNTP + if ((seconds > CHIP_SYSTEM_CONFIG_VALID_REAL_TIME_THRESHOLD) && (uSeconds > 0)) + { + curTime = Microseconds64((static_cast(seconds) * UINT64_C(1000000)) + static_cast(uSeconds)); + } +#endif return System::SystemClock().SetClock_RealTime(curTime); } From c197bc2db8c2079aa2af78c55fc647d048a70b5b Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Tue, 19 Nov 2024 16:44:34 -0800 Subject: [PATCH 054/219] Add APIs to access default SessionKeystore & PersistentStorageDelegate (#36566) * Add APIs to access default SessionKeystore & PersistentStorageDelegate * Restyled by whitespace --------- Co-authored-by: Restyled.io --- examples/platform/linux/CommissionerMain.cpp | 10 ++++++++++ examples/platform/linux/CommissionerMain.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/examples/platform/linux/CommissionerMain.cpp b/examples/platform/linux/CommissionerMain.cpp index e8da5d70b2..300d2466bc 100644 --- a/examples/platform/linux/CommissionerMain.cpp +++ b/examples/platform/linux/CommissionerMain.cpp @@ -457,4 +457,14 @@ CommissionerDiscoveryController * GetCommissionerDiscoveryController() return &gCommissionerDiscoveryController; } +SessionKeystore * GetSessionKeystore() +{ + return &gSessionKeystore; +} + +PersistentStorageDelegate * GetPersistentStorageDelegate() +{ + return &gServerStorage; +} + #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE diff --git a/examples/platform/linux/CommissionerMain.h b/examples/platform/linux/CommissionerMain.h index e241d436c4..106e94b0ed 100644 --- a/examples/platform/linux/CommissionerMain.h +++ b/examples/platform/linux/CommissionerMain.h @@ -28,7 +28,9 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE +using chip::PersistentStorageDelegate; using chip::Controller::DeviceCommissioner; +using chip::Crypto::SessionKeystore; using chip::Transport::PeerAddress; CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, PeerAddress address); @@ -39,5 +41,7 @@ void ShutdownCommissioner(); DeviceCommissioner * GetDeviceCommissioner(); CommissionerDiscoveryController * GetCommissionerDiscoveryController(); +SessionKeystore * GetSessionKeystore(); +PersistentStorageDelegate * GetPersistentStorageDelegate(); #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE From f4b806467e573b3c7b9cb7fa27597681d98f4c1c Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Wed, 20 Nov 2024 06:28:03 -0800 Subject: [PATCH 055/219] [Fabric-Sync] Support icd-registration during device sync (#36569) --- examples/fabric-sync/admin/BUILD.gn | 6 + examples/fabric-sync/admin/FabricAdmin.cpp | 64 +++++++++- examples/fabric-sync/admin/FabricAdmin.h | 14 ++- examples/fabric-sync/admin/IcdManager.cpp | 51 ++++++++ examples/fabric-sync/admin/IcdManager.h | 55 +++++++++ examples/fabric-sync/admin/PairingManager.cpp | 92 ++++++++++++++- examples/fabric-sync/admin/PairingManager.h | 11 ++ .../fabric-sync/admin/StayActiveSender.cpp | 103 ++++++++++++++++ examples/fabric-sync/admin/StayActiveSender.h | 111 ++++++++++++++++++ examples/platform/linux/AppMain.h | 5 + 10 files changed, 507 insertions(+), 5 deletions(-) create mode 100644 examples/fabric-sync/admin/IcdManager.cpp create mode 100644 examples/fabric-sync/admin/IcdManager.h create mode 100644 examples/fabric-sync/admin/StayActiveSender.cpp create mode 100644 examples/fabric-sync/admin/StayActiveSender.h diff --git a/examples/fabric-sync/admin/BUILD.gn b/examples/fabric-sync/admin/BUILD.gn index 2ccc30ca2f..e53590388e 100644 --- a/examples/fabric-sync/admin/BUILD.gn +++ b/examples/fabric-sync/admin/BUILD.gn @@ -44,8 +44,12 @@ source_set("fabric-admin-lib") { "FabricAdmin.h", "FabricSyncGetter.cpp", "FabricSyncGetter.h", + "IcdManager.cpp", + "IcdManager.h", "PairingManager.cpp", "PairingManager.h", + "StayActiveSender.cpp", + "StayActiveSender.h", "UniqueIdGetter.cpp", "UniqueIdGetter.h", ] @@ -53,6 +57,8 @@ source_set("fabric-admin-lib") { deps = [ "${chip_root}/examples/fabric-sync/bridge:fabric-bridge-lib", "${chip_root}/examples/platform/linux:app-main", + "${chip_root}/src/app/icd/client:handler", + "${chip_root}/src/app/icd/client:manager", "${chip_root}/src/lib", ] } diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index ed2126d34e..afc9456b2a 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -16,6 +16,9 @@ */ #include "FabricAdmin.h" +#include +#include +#include using namespace ::chip; @@ -28,16 +31,35 @@ constexpr uint32_t kCommissionPrepareTimeMs = 500; } // namespace FabricAdmin FabricAdmin::sInstance; +app::DefaultICDClientStorage FabricAdmin::sICDClientStorage; +app::CheckInHandler FabricAdmin::sCheckInHandler; FabricAdmin & FabricAdmin::Instance() { if (!sInstance.mInitialized) { - sInstance.Init(); + VerifyOrDie(sInstance.Init() == CHIP_NO_ERROR); } return sInstance; } +CHIP_ERROR FabricAdmin::Init() +{ + IcdManager::Instance().SetDelegate(&sInstance); + + ReturnLogErrorOnFailure(sICDClientStorage.Init(GetPersistentStorageDelegate(), GetSessionKeystore())); + + auto engine = chip::app::InteractionModelEngine::GetInstance(); + VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnLogErrorOnFailure(IcdManager::Instance().Init(&sICDClientStorage, engine)); + ReturnLogErrorOnFailure(sCheckInHandler.Init(Controller::DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), + &sICDClientStorage, &IcdManager::Instance(), engine)); + + mInitialized = true; + + return CHIP_NO_ERROR; +} + CHIP_ERROR FabricAdmin::OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams params, FabricIndex fabricIndex) { ScopedNodeId scopedNodeId(params.GetNodeId(), fabricIndex); @@ -116,6 +138,46 @@ CHIP_ERROR FabricAdmin::KeepActive(ScopedNodeId scopedNodeId, uint32_t stayActiv return CHIP_NO_ERROR; } +void FabricAdmin::OnCheckInCompleted(const app::ICDClientInfo & clientInfo) +{ + // Accessing mPendingCheckIn should only be done while holding ChipStackLock + assertChipStackLockedByCurrentThread(); + ScopedNodeId scopedNodeId = clientInfo.peer_node; + auto it = mPendingCheckIn.find(scopedNodeId); + VerifyOrReturn(it != mPendingCheckIn.end()); + + KeepActiveDataForCheckIn checkInData = it->second; + // Removed from pending map as check-in from this node has occured and we will handle the pending KeepActive + // request. + mPendingCheckIn.erase(scopedNodeId); + + auto timeNow = System::SystemClock().GetMonotonicTimestamp(); + if (timeNow > checkInData.mRequestExpiryTimestamp) + { + ChipLogError(NotSpecified, + "ICD check-in for device we have been waiting, came after KeepActive expiry. Request dropped for ID: " + "[%d:0x " ChipLogFormatX64 "]", + scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId())); + return; + } + + // TODO https://github.com/CHIP-Specifications/connectedhomeip-spec/issues/10448. Spec does + // not define what to do if we fail to send the StayActiveRequest. We are assuming that any + // further attempts to send a StayActiveRequest will result in a similar failure. Because + // there is no mechanism for us to communicate with the client that sent out the KeepActive + // command that there was a failure, we simply fail silently. After spec issue is + // addressed, we can implement what spec defines here. + auto onDone = [=](uint32_t promisedActiveDuration) { + bridge::FabricBridge::Instance().ActiveChanged(scopedNodeId, promisedActiveDuration); + }; + CHIP_ERROR err = StayActiveSender::SendStayActiveCommand(checkInData.mStayActiveDurationMs, clientInfo.peer_node, + app::InteractionModelEngine::GetInstance(), onDone); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to send StayActive command %s", err.AsString()); + } +} + void FabricAdmin::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { if (mNodeId != deviceId) diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h index f2634156ee..85547373f1 100644 --- a/examples/fabric-sync/admin/FabricAdmin.h +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -18,7 +18,12 @@ #pragma once #include "DeviceManager.h" +#include "IcdManager.h" +#include "StayActiveSender.h" +#include +#include +#include #include #include #include @@ -37,10 +42,11 @@ struct ScopedNodeIdHasher } }; -class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDelegate +class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDelegate, public IcdManager::Delegate { public: static FabricAdmin & Instance(); + static chip::app::DefaultICDClientStorage & GetDefaultICDClientStorage() { return sICDClientStorage; } CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, chip::FabricIndex fabricIndex) override; @@ -51,6 +57,8 @@ class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDele CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) override; + void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) override; + void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR err) override; void ScheduleSendingKeepActiveOnCheckIn(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs); @@ -89,11 +97,13 @@ class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDele std::unordered_map mPendingCheckIn; static FabricAdmin sInstance; + static chip::app::DefaultICDClientStorage sICDClientStorage; + static chip::app::CheckInHandler sCheckInHandler; bool mInitialized = false; chip::NodeId mNodeId = chip::kUndefinedNodeId; - void Init() { mInitialized = true; } + CHIP_ERROR Init(); }; } // namespace admin diff --git a/examples/fabric-sync/admin/IcdManager.cpp b/examples/fabric-sync/admin/IcdManager.cpp new file mode 100644 index 0000000000..75c49a7fd9 --- /dev/null +++ b/examples/fabric-sync/admin/IcdManager.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#include "IcdManager.h" + +namespace admin { + +IcdManager IcdManager::sInstance; + +IcdManager & IcdManager::Instance() +{ + return sInstance; +} + +void IcdManager::OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) +{ + DefaultCheckInDelegate::OnCheckInComplete(clientInfo); + if (mDelegate) + { + mDelegate->OnCheckInCompleted(clientInfo); + } +} + +void IcdManager::SetDelegate(Delegate * delegate) +{ + // To keep IcdManager simple, there is an assumption that there is only ever + // one delegate set and it's lifetime is identical to IcdManager. In the + // future this assumption can change should there be a need, but that will + // require code changes to IcdManager. For now we will crash if someone tries + // to call SetDelegate for a second time or if delegate is non-null. + VerifyOrDie(delegate); + VerifyOrDie(!mDelegate); + mDelegate = delegate; +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/IcdManager.h b/examples/fabric-sync/admin/IcdManager.h new file mode 100644 index 0000000000..0700363bf5 --- /dev/null +++ b/examples/fabric-sync/admin/IcdManager.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + * + */ + +#pragma once + +#include + +namespace admin { + +/** + * @brief Manages check-ins from ICD devices. + * + * Intended to be used as a thin CheckInDelegate. This allows a delegate register + * themselves so they can be aware when ICD device checks-in allowing the + * delegate to interact with the ICD device during the short window that it is + * awake. + */ +class IcdManager : public chip::app::DefaultCheckInDelegate +{ +public: + class Delegate + { + public: + virtual ~Delegate() = default; + virtual void OnCheckInCompleted(const chip::app::ICDClientInfo & clientInfo) = 0; + }; + + static IcdManager & Instance(); + void OnCheckInComplete(const chip::app::ICDClientInfo & clientInfo) override; + + // There is an assumption delegate assigned only happens once and that it lives + // for the entirety of the lifetime of fabric admin. + void SetDelegate(Delegate * delegate); + +private: + static IcdManager sInstance; + Delegate * mDelegate = nullptr; +}; + +} // namespace admin diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index eeb8ad09ff..63a2c67c84 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -18,6 +18,7 @@ #include "PairingManager.h" #include "DeviceManager.h" #include "DeviceSynchronization.h" +#include "FabricAdmin.h" #include #include @@ -103,7 +104,7 @@ PairingManager::PairingManager() : CHIP_ERROR PairingManager::Init(Controller::DeviceCommissioner * commissioner) { VerifyOrReturnError(commissioner != nullptr, CHIP_ERROR_INCORRECT_STATE); - + FabricAdmin::Instance().GetDefaultICDClientStorage().UpdateFabricList(commissioner->GetFabricIndex()); mCommissioner = commissioner; return CHIP_NO_ERROR; @@ -294,10 +295,20 @@ void PairingManager::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err) // mCommissioner has a lifetime that is the entire life of the application itself // so it is safe to provide to StartDeviceSynchronization. - DeviceSynchronizer::Instance().StartDeviceSynchronization(mCommissioner, nodeId, false); + DeviceSynchronizer::Instance().StartDeviceSynchronization(mCommissioner, nodeId, mDeviceIsICD); } else { + // When ICD device commissioning fails, the ICDClientInfo stored in OnICDRegistrationComplete needs to be removed. + if (mDeviceIsICD) + { + CHIP_ERROR deleteEntryError = FabricAdmin::Instance().GetDefaultICDClientStorage().DeleteEntry( + ScopedNodeId(nodeId, mCommissioner->GetFabricIndex())); + if (deleteEntryError != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to delete ICD entry: %s", ErrorStr(err)); + } + } ChipLogProgress(NotSpecified, "Device commissioning Failure: %s", ErrorStr(err)); } } @@ -329,6 +340,49 @@ void PairingManager::OnReadCommissioningInfo(const Controller::ReadCommissioning info.icd.idleModeDuration, info.icd.activeModeDuration, info.icd.activeModeThreshold); } +void PairingManager::OnICDRegistrationComplete(ScopedNodeId nodeId, uint32_t icdCounter) +{ + char icdSymmetricKeyHex[Crypto::kAES_CCM128_Key_Length * 2 + 1]; + + Encoding::BytesToHex(mICDSymmetricKey.Value().data(), mICDSymmetricKey.Value().size(), icdSymmetricKeyHex, + sizeof(icdSymmetricKeyHex), Encoding::HexFlags::kNullTerminate); + + app::ICDClientInfo clientInfo; + clientInfo.peer_node = nodeId; + clientInfo.monitored_subject = mICDMonitoredSubject.Value(); + clientInfo.start_icd_counter = icdCounter; + auto & ICDClientStorage = FabricAdmin::Instance().GetDefaultICDClientStorage(); + + CHIP_ERROR err = ICDClientStorage.SetKey(clientInfo, mICDSymmetricKey.Value()); + if (err == CHIP_NO_ERROR) + { + err = ICDClientStorage.StoreEntry(clientInfo); + } + + if (err != CHIP_NO_ERROR) + { + ICDClientStorage.RemoveKey(clientInfo); + ChipLogError(NotSpecified, "Failed to persist symmetric key for " ChipLogFormatX64 ": %s", + ChipLogValueX64(nodeId.GetNodeId()), err.AsString()); + return; + } + + mDeviceIsICD = true; + + ChipLogProgress(NotSpecified, "Saved ICD Symmetric key for " ChipLogFormatX64, ChipLogValueX64(nodeId.GetNodeId())); + ChipLogProgress(NotSpecified, + "ICD Registration Complete for device " ChipLogFormatX64 " / Check-In NodeID: " ChipLogFormatX64 + " / Monitored Subject: " ChipLogFormatX64 " / Symmetric Key: %s / ICDCounter %u", + ChipLogValueX64(nodeId.GetNodeId()), ChipLogValueX64(mICDCheckInNodeId.Value()), + ChipLogValueX64(mICDMonitoredSubject.Value()), icdSymmetricKeyHex, icdCounter); +} + +void PairingManager::OnICDStayActiveComplete(ScopedNodeId deviceId, uint32_t promisedActiveDuration) +{ + ChipLogProgress(NotSpecified, "ICD Stay Active Complete for device " ChipLogFormatX64 " / promisedActiveDuration: %u", + ChipLogValueX64(deviceId.GetNodeId()), promisedActiveDuration); +} + void PairingManager::OnDiscoveredDevice(const Dnssd::CommissionNodeData & nodeData) { // Ignore nodes with closed commissioning window @@ -436,6 +490,39 @@ CommissioningParameters PairingManager::GetCommissioningParameters() params.SetSkipCommissioningComplete(false); params.SetDeviceAttestationDelegate(this); + if (mICDRegistration.ValueOr(false)) + { + params.SetICDRegistrationStrategy(ICDRegistrationStrategy::kBeforeComplete); + + if (!mICDSymmetricKey.HasValue()) + { + Crypto::DRBG_get_bytes(mRandomGeneratedICDSymmetricKey, sizeof(mRandomGeneratedICDSymmetricKey)); + mICDSymmetricKey.SetValue(ByteSpan(mRandomGeneratedICDSymmetricKey)); + } + if (!mICDCheckInNodeId.HasValue()) + { + mICDCheckInNodeId.SetValue(mCommissioner->GetNodeId()); + } + if (!mICDMonitoredSubject.HasValue()) + { + mICDMonitoredSubject.SetValue(mICDCheckInNodeId.Value()); + } + if (!mICDClientType.HasValue()) + { + mICDClientType.SetValue(app::Clusters::IcdManagement::ClientTypeEnum::kPermanent); + } + // These Optionals must have values now. + // The commissioner will verify these values. + params.SetICDSymmetricKey(mICDSymmetricKey.Value()); + if (mICDStayActiveDurationMsec.HasValue()) + { + params.SetICDStayActiveDurationMsec(mICDStayActiveDurationMsec.Value()); + } + params.SetICDCheckInNodeId(mICDCheckInNodeId.Value()); + params.SetICDMonitoredSubject(mICDMonitoredSubject.Value()); + params.SetICDClientType(mICDClientType.Value()); + } + return params; } @@ -482,6 +569,7 @@ void PairingManager::OnCurrentFabricRemove(void * context, NodeId nodeId, CHIP_E void PairingManager::InitPairingCommand() { mCommissioner->RegisterPairingDelegate(this); + mDeviceIsICD = false; } CHIP_ERROR PairingManager::PairDeviceWithCode(NodeId nodeId, const char * payload) diff --git a/examples/fabric-sync/admin/PairingManager.h b/examples/fabric-sync/admin/PairingManager.h index 9d109911e1..37e9aedec6 100644 --- a/examples/fabric-sync/admin/PairingManager.h +++ b/examples/fabric-sync/admin/PairingManager.h @@ -149,6 +149,8 @@ class PairingManager : public chip::Controller::DevicePairingDelegate, void OnPairingDeleted(CHIP_ERROR error) override; void OnReadCommissioningInfo(const chip::Controller::ReadCommissioningInfo & info) override; void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR error) override; + void OnICDRegistrationComplete(chip::ScopedNodeId deviceId, uint32_t icdCounter) override; + void OnICDStayActiveComplete(chip::ScopedNodeId deviceId, uint32_t promisedActiveDuration) override; /////////// DeviceDiscoveryDelegate Interface ///////// void OnDiscoveredDevice(const chip::Dnssd::CommissionNodeData & nodeData) override; @@ -176,11 +178,20 @@ class PairingManager : public chip::Controller::DevicePairingDelegate, chip::ByteSpan mSalt; uint16_t mDiscriminator = 0; uint32_t mSetupPINCode = 0; + bool mDeviceIsICD = false; + uint8_t mRandomGeneratedICDSymmetricKey[chip::Crypto::kAES_CCM128_Key_Length]; uint8_t mVerifierBuffer[chip::Crypto::kSpake2p_VerifierSerialized_Length]; uint8_t mSaltBuffer[chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length]; char mRemoteIpAddr[chip::Inet::IPAddress::kMaxStringLength]; char mOnboardingPayload[kMaxManualCodeLength + 1]; + chip::Optional mICDRegistration; + chip::Optional mICDCheckInNodeId; + chip::Optional mICDClientType; + chip::Optional mICDSymmetricKey; + chip::Optional mICDMonitoredSubject; + chip::Optional mICDStayActiveDurationMsec; + /** * Holds the unique_ptr to the current CommissioningWindowOpener. * Only one commissioning window opener can be active at a time. diff --git a/examples/fabric-sync/admin/StayActiveSender.cpp b/examples/fabric-sync/admin/StayActiveSender.cpp new file mode 100644 index 0000000000..51927c4d59 --- /dev/null +++ b/examples/fabric-sync/admin/StayActiveSender.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "StayActiveSender.h" + +#include +#include +#include +#include + +namespace admin { + +CHIP_ERROR StayActiveSender::SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, + chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone) +{ + ConstructorOnlyInternallyCallable internal; + auto stayActiveSender = chip::Platform::New(internal, stayActiveDurationMs, peerNode, + chip::app::InteractionModelEngine::GetInstance(), onDone); + VerifyOrReturnError(stayActiveSender != nullptr, CHIP_ERROR_NO_MEMORY); + CHIP_ERROR err = stayActiveSender->EstablishSessionToPeer(); + if (CHIP_NO_ERROR != err) + { + chip::Platform::Delete(stayActiveSender); + } + return err; +} + +StayActiveSender::StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, + const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, + OnDoneCallbackType onDone) : + mStayActiveDurationMs(stayActiveDurationMs), + mPeerNode(peerNode), mpImEngine(engine), mOnDone(onDone), mOnConnectedCallback(HandleDeviceConnected, this), + mOnConnectionFailureCallback(HandleDeviceConnectionFailure, this) +{} + +CHIP_ERROR StayActiveSender::SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + auto onSuccess = [&](const chip::app::ConcreteCommandPath & commandPath, const chip::app::StatusIB & status, + const auto & dataResponse) { + uint32_t promisedActiveDurationMs = dataResponse.promisedActiveDuration; + ChipLogProgress(ICD, "StayActive command succeeded with promised duration %u", promisedActiveDurationMs); + mOnDone(promisedActiveDurationMs); + chip::Platform::Delete(this); + }; + + auto onFailure = [&](CHIP_ERROR error) { + ChipLogError(ICD, "StayActive command failed: %" CHIP_ERROR_FORMAT, error.Format()); + chip::Platform::Delete(this); + }; + + chip::EndpointId endpointId = 0; + chip::app::Clusters::IcdManagement::Commands::StayActiveRequest::Type request; + request.stayActiveDuration = mStayActiveDurationMs; + return chip::Controller::InvokeCommandRequest(&exchangeMgr, sessionHandle, endpointId, request, onSuccess, onFailure); +} + +CHIP_ERROR StayActiveSender::EstablishSessionToPeer() +{ + ChipLogProgress(ICD, "Trying to establish a CASE session to extend the active period for lit icd device"); + auto * caseSessionManager = mpImEngine->GetCASESessionManager(); + VerifyOrReturnError(caseSessionManager != nullptr, CHIP_ERROR_INVALID_CASE_PARAMETER); + caseSessionManager->FindOrEstablishSession(mPeerNode, &mOnConnectedCallback, &mOnConnectionFailureCallback); + return CHIP_NO_ERROR; +} + +void StayActiveSender::HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle) +{ + StayActiveSender * const _this = static_cast(context); + VerifyOrDie(_this != nullptr); + + CHIP_ERROR err = _this->SendStayActiveCommand(exchangeMgr, sessionHandle); + if (CHIP_NO_ERROR != err) + { + ChipLogError(ICD, "Failed to send stay active command"); + chip::Platform::Delete(_this); + } +} + +void StayActiveSender::HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err) +{ + StayActiveSender * const _this = static_cast(context); + VerifyOrDie(_this != nullptr); + ChipLogError(ICD, "Failed to establish CASE for stay active command with error '%" CHIP_ERROR_FORMAT "'", err.Format()); + chip::Platform::Delete(_this); +} + +} // namespace admin diff --git a/examples/fabric-sync/admin/StayActiveSender.h b/examples/fabric-sync/admin/StayActiveSender.h new file mode 100644 index 0000000000..dd4a66dded --- /dev/null +++ b/examples/fabric-sync/admin/StayActiveSender.h @@ -0,0 +1,111 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#pragma once + +#include + +#include +#include +#include + +namespace admin { + +/** + * @brief StayActiveSender contains all the data and methods needed for active period extension of an ICD client. + * + * Lifetime of instance of StayActiveSender is entirely self managed. + */ +class StayActiveSender +{ +private: + // Ideally StayActiveSender would be a private constructor, unfortunately that is not possible as Platform::New + // does not have access to private constructors. As a workaround we have defined this private struct that can + // be forwarded by Platform::New that allows us to enforce that the only way StayActiveSender is constructed is + // if SendStayActiveCommand is called. + struct ConstructorOnlyInternallyCallable + { + }; + +public: + using OnDoneCallbackType = std::function; + + /** + * @brief Attempts to send a StayActiveRequest command + * + * @param[in] stayActiveDurationMs StayActiveRequest command parameter. + * @param[in] peerNode Peer node we sending StayActiveRequest command to + * @param[in] engine Interaction Model Engine instance for sending command. + * @param[in] onDone Upon this function returning success, it is expected that onDone will be called after we + * have successfully recieved a response + * + * @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code. + */ + static CHIP_ERROR SendStayActiveCommand(uint32_t stayActiveDurationMs, const chip::ScopedNodeId & peerNode, + chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); + + // Ideally this would be a private constructor, unfortunately that is not possible as Platform::New does not + // have access to private constructors. As a workaround we have defined a private struct that can be forwarded + // by Platform::New that allows us to enforce that the only way this is constructed is if SendStayActiveCommand + // is called. + StayActiveSender(const ConstructorOnlyInternallyCallable & _, uint32_t stayActiveDurationMs, + const chip::ScopedNodeId & peerNode, chip::app::InteractionModelEngine * engine, OnDoneCallbackType onDone); + +private: + /** + * @brief Sets up a CASE session with the peer to extend the client's active period with that peer. + * Returns error if we did not even manage to kick off a CASE attempt. + */ + CHIP_ERROR EstablishSessionToPeer(); + + // CASE session callbacks + /** + *@brief Callback received on successfully establishing a CASE session in order to keep the 'lit icd device' active + * + * @param[in] context - context of the client establishing the CASE session + * @param[in] exchangeMgr - exchange manager to use for the re-registration + * @param[in] sessionHandle - session handle to use for the re-registration + */ + static void HandleDeviceConnected(void * context, chip::Messaging::ExchangeManager & exchangeMgr, + const chip::SessionHandle & sessionHandle); + /** + * @brief Callback received on failure to establish a CASE session + * + * @param[in] context - context of the client establishing the CASE session + * @param[in] peerId - Scoped Node ID of the peer node + * @param[in] err - failure reason + */ + static void HandleDeviceConnectionFailure(void * context, const chip::ScopedNodeId & peerId, CHIP_ERROR err); + + /** + * @brief Used to send a stayActive command to the peer + * + * @param[in] exchangeMgr - exchange manager to use for the re-registration + * @param[in] sessionHandle - session handle to use for the re-registration + */ + CHIP_ERROR SendStayActiveCommand(chip::Messaging::ExchangeManager & exchangeMgr, const chip::SessionHandle & sessionHandle); + + uint32_t mStayActiveDurationMs = 0; + chip::ScopedNodeId mPeerNode; + chip::app::InteractionModelEngine * mpImEngine = nullptr; + OnDoneCallbackType mOnDone; + + chip::Callback::Callback mOnConnectedCallback; + chip::Callback::Callback mOnConnectionFailureCallback; +}; + +} // namespace admin diff --git a/examples/platform/linux/AppMain.h b/examples/platform/linux/AppMain.h index 94bf4d3e60..21ba04df7d 100644 --- a/examples/platform/linux/AppMain.h +++ b/examples/platform/linux/AppMain.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,9 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl = nullptr); #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE +using chip::PersistentStorageDelegate; using chip::Controller::DeviceCommissioner; +using chip::Crypto::SessionKeystore; using chip::Transport::PeerAddress; CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, PeerAddress address); @@ -98,6 +101,8 @@ CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index); DeviceCommissioner * GetDeviceCommissioner(); CommissionerDiscoveryController * GetCommissionerDiscoveryController(); +SessionKeystore * GetSessionKeystore(); +PersistentStorageDelegate * GetPersistentStorageDelegate(); #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE From 007f4d79c1a2f1c4935c4eaf2004f78a6e63c0c2 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Wed, 20 Nov 2024 16:48:12 +0200 Subject: [PATCH 056/219] [Telink] Improve B92 retention target & Update builds to docker version 93 (#36552) * riscv:b92: fix ble thread overflow. - cut down the ramcost for b92 retention mode. - move the .ramcode to retention . Signed-off-by: Haiwen Xia * Restyled by whitespace * Restyled by clang-format * [Telink] Update hash of latest Zephyr to check builds * [Telink] Update builds to docker version 93 * riscv:b92: clean code and adjust config. - change the kconfig.default value . - merge the same setting for save ram. Signed-off-by: Haiwen Xia * [Telink] Update builds to docker version 93 --------- Signed-off-by: Haiwen Xia Co-authored-by: Haiwen Xia Co-authored-by: Restyled.io --- .github/workflows/bloat_check.yaml | 2 +- .github/workflows/build.yaml | 10 +++++----- .github/workflows/chef.yaml | 10 +++++----- .github/workflows/doxygen.yaml | 2 +- .github/workflows/examples-ameba.yaml | 2 +- .github/workflows/examples-asr.yaml | 2 +- .github/workflows/examples-bouffalolab.yaml | 2 +- .github/workflows/examples-cc13xx_26xx.yaml | 2 +- .github/workflows/examples-cc32xx.yaml | 2 +- .github/workflows/examples-efr32.yaml | 2 +- .github/workflows/examples-esp32.yaml | 4 ++-- .github/workflows/examples-infineon.yaml | 2 +- .github/workflows/examples-linux-arm.yaml | 2 +- .github/workflows/examples-linux-imx.yaml | 2 +- .github/workflows/examples-linux-standalone.yaml | 2 +- .../workflows/examples-linux-tv-casting-app.yaml | 2 +- .github/workflows/examples-mw320.yaml | 2 +- .github/workflows/examples-nrfconnect.yaml | 2 +- .github/workflows/examples-nuttx.yaml | 2 +- .github/workflows/examples-nxp.yaml | 4 ++-- .github/workflows/examples-openiotsdk.yaml | 2 +- .github/workflows/examples-qpg.yaml | 2 +- .github/workflows/examples-stm32.yaml | 2 +- .github/workflows/examples-telink.yaml | 4 ++-- .github/workflows/examples-tizen.yaml | 2 +- .github/workflows/full-android.yaml | 2 +- .github/workflows/fuzzing-build.yaml | 2 +- .github/workflows/java-tests.yaml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/minimal-build.yaml | 4 ++-- .github/workflows/qemu.yaml | 4 ++-- .github/workflows/release_artifacts.yaml | 4 ++-- .github/workflows/smoketest-android.yaml | 2 +- .github/workflows/tests.yaml | 4 ++-- .github/workflows/unit_integration_test.yaml | 2 +- .github/workflows/zap_regeneration.yaml | 2 +- .github/workflows/zap_templates.yaml | 2 +- config/telink/chip-module/Kconfig.defaults | 13 +++++++------ examples/all-clusters-app/ameba/README.md | 4 ++-- examples/all-clusters-minimal-app/ameba/README.md | 4 ++-- examples/fabric-admin/README.md | 4 ++-- examples/fabric-bridge-app/linux/README.md | 4 ++-- examples/fabric-sync/README.md | 4 ++-- examples/light-switch-app/ameba/README.md | 4 ++-- examples/lighting-app/ameba/README.md | 4 ++-- examples/ota-requestor-app/ameba/README.md | 4 ++-- examples/pigweed-app/ameba/README.md | 4 ++-- integrations/cloudbuild/chef.yaml | 8 ++++---- integrations/cloudbuild/smoke-test.yaml | 14 +++++++------- src/platform/telink/CHIPDevicePlatformConfig.h | 2 +- src/platform/telink/SystemPlatformConfig.h | 2 +- 51 files changed, 90 insertions(+), 89 deletions(-) diff --git a/.github/workflows/bloat_check.yaml b/.github/workflows/bloat_check.yaml index 465526ea87..be423b04c0 100644 --- a/.github/workflows/bloat_check.yaml +++ b/.github/workflows/bloat_check.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 steps: - name: Checkout diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4d16657b35..2539edcf6a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -43,7 +43,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -139,7 +139,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -308,7 +308,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -371,7 +371,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" @@ -490,7 +490,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/chef.yaml b/.github/workflows/chef.yaml index d2298bbca3..c897952d45 100644 --- a/.github/workflows/chef.yaml +++ b/.github/workflows/chef.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 options: --user root steps: @@ -57,7 +57,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:92 + image: ghcr.io/project-chip/chip-build-esp32:93 options: --user root steps: @@ -78,7 +78,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:92 + image: ghcr.io/project-chip/chip-build-nrf-platform:93 options: --user root steps: @@ -99,7 +99,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:92 + image: ghcr.io/project-chip/chip-build-telink:93 options: --user root steps: @@ -111,7 +111,7 @@ jobs: platform: telink # - name: Update Zephyr to specific revision (for developers purpose) # shell: bash - # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 9ab2325bf76bc7bec92a3ff93fad80ec5d3eae7c" + # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 8b29ee6b118ebe6eeec3224dbe343474e11403d8" - name: CI Examples Telink shell: bash run: | diff --git a/.github/workflows/doxygen.yaml b/.github/workflows/doxygen.yaml index 4af7b3d8ed..eb45f76f38 100644 --- a/.github/workflows/doxygen.yaml +++ b/.github/workflows/doxygen.yaml @@ -84,7 +84,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-doxygen:92 + image: ghcr.io/project-chip/chip-build-doxygen:93 if: github.actor != 'restyled-io[bot]' diff --git a/.github/workflows/examples-ameba.yaml b/.github/workflows/examples-ameba.yaml index 92ee46b49d..2c1c2555e7 100644 --- a/.github/workflows/examples-ameba.yaml +++ b/.github/workflows/examples-ameba.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ameba:92 + image: ghcr.io/project-chip/chip-build-ameba:93 options: --user root steps: diff --git a/.github/workflows/examples-asr.yaml b/.github/workflows/examples-asr.yaml index ce4fef94fd..61ac888ad4 100644 --- a/.github/workflows/examples-asr.yaml +++ b/.github/workflows/examples-asr.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-asr:92 + image: ghcr.io/project-chip/chip-build-asr:93 options: --user root steps: diff --git a/.github/workflows/examples-bouffalolab.yaml b/.github/workflows/examples-bouffalolab.yaml index ed6e583285..c0178a04c2 100644 --- a/.github/workflows/examples-bouffalolab.yaml +++ b/.github/workflows/examples-bouffalolab.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-bouffalolab:92 + image: ghcr.io/project-chip/chip-build-bouffalolab:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-cc13xx_26xx.yaml b/.github/workflows/examples-cc13xx_26xx.yaml index 68f5ecf09f..0aaec6d6cc 100644 --- a/.github/workflows/examples-cc13xx_26xx.yaml +++ b/.github/workflows/examples-cc13xx_26xx.yaml @@ -42,7 +42,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ti:92 + image: ghcr.io/project-chip/chip-build-ti:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-cc32xx.yaml b/.github/workflows/examples-cc32xx.yaml index 935c5df723..c7615bc27d 100644 --- a/.github/workflows/examples-cc32xx.yaml +++ b/.github/workflows/examples-cc32xx.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-ti:92 + image: ghcr.io/project-chip/chip-build-ti:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-efr32.yaml b/.github/workflows/examples-efr32.yaml index 1b970abf6a..8e40a0df99 100644 --- a/.github/workflows/examples-efr32.yaml +++ b/.github/workflows/examples-efr32.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-efr32:92 + image: ghcr.io/project-chip/chip-build-efr32:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index ba90be6082..20ced0375b 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-esp32:92 + image: ghcr.io/project-chip/chip-build-esp32:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -124,7 +124,7 @@ jobs: if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif' container: - image: ghcr.io/project-chip/chip-build-esp32:92 + image: ghcr.io/project-chip/chip-build-esp32:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-infineon.yaml b/.github/workflows/examples-infineon.yaml index 165d9015fa..5b7ee30abe 100644 --- a/.github/workflows/examples-infineon.yaml +++ b/.github/workflows/examples-infineon.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-infineon:92 + image: ghcr.io/project-chip/chip-build-infineon:93 env: # TODO: this should probably be part of the dockerfile itself CY_TOOLS_PATHS: /opt/Tools/ModusToolbox/tools_3.2 diff --git a/.github/workflows/examples-linux-arm.yaml b/.github/workflows/examples-linux-arm.yaml index 5815d1d1d3..84a36addb8 100644 --- a/.github/workflows/examples-linux-arm.yaml +++ b/.github/workflows/examples-linux-arm.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-crosscompile:92 + image: ghcr.io/project-chip/chip-build-crosscompile:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-imx.yaml b/.github/workflows/examples-linux-imx.yaml index 69d832282a..33098465c1 100644 --- a/.github/workflows/examples-linux-imx.yaml +++ b/.github/workflows/examples-linux-imx.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-imx:92 + image: ghcr.io/project-chip/chip-build-imx:93 steps: - name: Checkout diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index 5c1fbcbdf6..b4ed1cd92d 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-linux-tv-casting-app.yaml b/.github/workflows/examples-linux-tv-casting-app.yaml index 8480509c00..4bc173f7cc 100644 --- a/.github/workflows/examples-linux-tv-casting-app.yaml +++ b/.github/workflows/examples-linux-tv-casting-app.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 steps: - name: Checkout diff --git a/.github/workflows/examples-mw320.yaml b/.github/workflows/examples-mw320.yaml index 65a23f6b1a..5b2d082ff5 100644 --- a/.github/workflows/examples-mw320.yaml +++ b/.github/workflows/examples-mw320.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nrfconnect.yaml b/.github/workflows/examples-nrfconnect.yaml index bc8fbde4da..0aff592c54 100644 --- a/.github/workflows/examples-nrfconnect.yaml +++ b/.github/workflows/examples-nrfconnect.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nrf-platform:92 + image: ghcr.io/project-chip/chip-build-nrf-platform:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/examples-nuttx.yaml b/.github/workflows/examples-nuttx.yaml index e9b214f3e4..63088ce8f7 100644 --- a/.github/workflows/examples-nuttx.yaml +++ b/.github/workflows/examples-nuttx.yaml @@ -38,7 +38,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nuttx:92 + image: ghcr.io/project-chip/chip-build-nuttx:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-nxp.yaml b/.github/workflows/examples-nxp.yaml index 9348baa833..267045cca4 100644 --- a/.github/workflows/examples-nxp.yaml +++ b/.github/workflows/examples-nxp.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp:92 + image: ghcr.io/project-chip/chip-build-nxp:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: @@ -240,7 +240,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-nxp-zephyr:92 + image: ghcr.io/project-chip/chip-build-nxp-zephyr:93 steps: - name: Checkout diff --git a/.github/workflows/examples-openiotsdk.yaml b/.github/workflows/examples-openiotsdk.yaml index 4ff65c0c94..2727b81b86 100644 --- a/.github/workflows/examples-openiotsdk.yaml +++ b/.github/workflows/examples-openiotsdk.yaml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-openiotsdk:92 + image: ghcr.io/project-chip/chip-build-openiotsdk:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" options: --privileged diff --git a/.github/workflows/examples-qpg.yaml b/.github/workflows/examples-qpg.yaml index 64f6678818..45e5b6a743 100644 --- a/.github/workflows/examples-qpg.yaml +++ b/.github/workflows/examples-qpg.yaml @@ -40,7 +40,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-stm32.yaml b/.github/workflows/examples-stm32.yaml index dad94e5267..e2ec5288ad 100644 --- a/.github/workflows/examples-stm32.yaml +++ b/.github/workflows/examples-stm32.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" steps: diff --git a/.github/workflows/examples-telink.yaml b/.github/workflows/examples-telink.yaml index c24b8f5565..1b6fd20aa7 100644 --- a/.github/workflows/examples-telink.yaml +++ b/.github/workflows/examples-telink.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-telink:92 + image: ghcr.io/project-chip/chip-build-telink:93 volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" @@ -58,7 +58,7 @@ jobs: gh-context: ${{ toJson(github) }} # - name: Update Zephyr to specific revision (for developers purpose) - # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 9ab2325bf76bc7bec92a3ff93fad80ec5d3eae7c" + # run: scripts/run_in_build_env.sh "python3 scripts/tools/telink/update_zephyr.py 8b29ee6b118ebe6eeec3224dbe343474e11403d8" - name: Build example Telink (B92 retention) Air Quality Sensor App # Run test for master and s07641069 PRs diff --git a/.github/workflows/examples-tizen.yaml b/.github/workflows/examples-tizen.yaml index a16ad58ee0..56a018d533 100644 --- a/.github/workflows/examples-tizen.yaml +++ b/.github/workflows/examples-tizen.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen:92 + image: ghcr.io/project-chip/chip-build-tizen:93 options: --user root volumes: - "/tmp/bloat_reports:/tmp/bloat_reports" diff --git a/.github/workflows/full-android.yaml b/.github/workflows/full-android.yaml index a020b78d74..4beb8d101e 100644 --- a/.github/workflows/full-android.yaml +++ b/.github/workflows/full-android.yaml @@ -39,7 +39,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:92 + image: ghcr.io/project-chip/chip-build-android:93 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/fuzzing-build.yaml b/.github/workflows/fuzzing-build.yaml index 97da04937e..2c8fa9d7f3 100644 --- a/.github/workflows/fuzzing-build.yaml +++ b/.github/workflows/fuzzing-build.yaml @@ -33,7 +33,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index 114f406f90..504cb865a9 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-java:92 + image: ghcr.io/project-chip/chip-build-java:93 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9273dbe991..731d047f28 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 steps: - name: Checkout diff --git a/.github/workflows/minimal-build.yaml b/.github/workflows/minimal-build.yaml index 682cf3de20..f933cd69df 100644 --- a/.github/workflows/minimal-build.yaml +++ b/.github/workflows/minimal-build.yaml @@ -34,7 +34,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:92 + image: ghcr.io/project-chip/chip-build-minimal:93 steps: - name: Checkout @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-minimal:92 + image: ghcr.io/project-chip/chip-build-minimal:93 steps: - name: Checkout diff --git a/.github/workflows/qemu.yaml b/.github/workflows/qemu.yaml index 187d4b8f0c..2a2d52f23a 100644 --- a/.github/workflows/qemu.yaml +++ b/.github/workflows/qemu.yaml @@ -41,7 +41,7 @@ jobs: if: github.actor != 'restyled-io[bot]' && github.repository_owner == 'espressif' container: - image: ghcr.io/project-chip/chip-build-esp32-qemu:92 + image: ghcr.io/project-chip/chip-build-esp32-qemu:93 volumes: - "/tmp/log_output:/tmp/test_logs" @@ -79,7 +79,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-tizen-qemu:92 + image: ghcr.io/project-chip/chip-build-tizen-qemu:93 options: --user root volumes: - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/release_artifacts.yaml b/.github/workflows/release_artifacts.yaml index a50d5260b5..161d123d9e 100644 --- a/.github/workflows/release_artifacts.yaml +++ b/.github/workflows/release_artifacts.yaml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-esp32:92 + image: ghcr.io/project-chip/chip-build-esp32:93 steps: - name: Checkout @@ -64,7 +64,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build-efr32:92 + image: ghcr.io/project-chip/chip-build-efr32:93 steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/smoketest-android.yaml b/.github/workflows/smoketest-android.yaml index c3293e8eb9..114c072cbe 100644 --- a/.github/workflows/smoketest-android.yaml +++ b/.github/workflows/smoketest-android.yaml @@ -37,7 +37,7 @@ jobs: if: github.actor != 'restyled-io[bot]' container: - image: ghcr.io/project-chip/chip-build-android:92 + image: ghcr.io/project-chip/chip-build-android:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 384ebc59a9..ceee20818d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" @@ -457,7 +457,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 options: --privileged --sysctl "net.ipv6.conf.all.disable_ipv6=0 net.ipv4.conf.all.forwarding=0 net.ipv6.conf.all.forwarding=0" diff --git a/.github/workflows/unit_integration_test.yaml b/.github/workflows/unit_integration_test.yaml index 9b97c8d54e..449152bf21 100644 --- a/.github/workflows/unit_integration_test.yaml +++ b/.github/workflows/unit_integration_test.yaml @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 volumes: - "/:/runner-root-volume" - "/tmp/log_output:/tmp/test_logs" diff --git a/.github/workflows/zap_regeneration.yaml b/.github/workflows/zap_regeneration.yaml index 649b867ba5..0cba8cb97c 100644 --- a/.github/workflows/zap_regeneration.yaml +++ b/.github/workflows/zap_regeneration.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 defaults: run: shell: sh diff --git a/.github/workflows/zap_templates.yaml b/.github/workflows/zap_templates.yaml index 07f1bc4f2f..6900886aed 100644 --- a/.github/workflows/zap_templates.yaml +++ b/.github/workflows/zap_templates.yaml @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-20.04 container: - image: ghcr.io/project-chip/chip-build:92 + image: ghcr.io/project-chip/chip-build:93 defaults: run: shell: sh diff --git a/config/telink/chip-module/Kconfig.defaults b/config/telink/chip-module/Kconfig.defaults index c220b5991f..3503aae400 100644 --- a/config/telink/chip-module/Kconfig.defaults +++ b/config/telink/chip-module/Kconfig.defaults @@ -83,7 +83,7 @@ config HEAP_MEM_POOL_SIZE default 256 config COMMON_LIBC_MALLOC_ARENA_SIZE - default 20716 if SOC_RISCV_TELINK_TL321X + default 20716 if SOC_RISCV_TELINK_TL321X || SOC_SERIES_RISCV_TELINK_B9X_RETENTION default 12288 config NET_IPV6_MLD @@ -104,13 +104,11 @@ config NET_PKT_TX_COUNT default 8 config NET_BUF_RX_COUNT - default 16 if PM - default 12 if SOC_RISCV_TELINK_TL321X + default 12 if PM || SOC_RISCV_TELINK_TL321X default 32 config NET_BUF_TX_COUNT - default 16 if PM - default 12 if SOC_RISCV_TELINK_TL321X + default 12 if PM || SOC_RISCV_TELINK_TL321X default 32 config GPIO @@ -206,9 +204,12 @@ endif # SOC_SERIES_RISCV_TELINK_B9X || SOC_SERIES_RISCV_TELINK_TLX endif # BT # Board retention config +# Cut down the ram cost by matter's change,it can keep ramcode (driver). +# No need load the ramcode every time in thread mode (retention mode). +# If the ram is not enough , can change it back , initial setting is n. if BOARD_TLSR9528A_RETENTION || BOARD_TLSR9258A_RETENTION || BOARD_TLSR9518ADK80D_RETENTION config SOC_SERIES_RISCV_TELINK_B9X_NON_RETENTION_RAM_CODE - default y if PM + default n if PM config TELINK_B9X_MATTER_RETENTION_LAYOUT default y if PM diff --git a/examples/all-clusters-app/ameba/README.md b/examples/all-clusters-app/ameba/README.md index 53b4b6ce87..828dd567da 100644 --- a/examples/all-clusters-app/ameba/README.md +++ b/examples/all-clusters-app/ameba/README.md @@ -27,11 +27,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:92 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/all-clusters-minimal-app/ameba/README.md b/examples/all-clusters-minimal-app/ameba/README.md index f50cfee5e4..947a9ed09f 100644 --- a/examples/all-clusters-minimal-app/ameba/README.md +++ b/examples/all-clusters-minimal-app/ameba/README.md @@ -27,13 +27,13 @@ The CHIP demo application is supported on - Pull docker image: ``` - $ docker pull ghcr.io/project-chip/chip-build-ameba:92 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 ``` - Run docker container: ``` - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 ``` - Setup build environment: diff --git a/examples/fabric-admin/README.md b/examples/fabric-admin/README.md index d9fb67de46..3ec2cb9967 100644 --- a/examples/fabric-admin/README.md +++ b/examples/fabric-admin/README.md @@ -23,13 +23,13 @@ For Raspberry Pi 4 example: ### Pull Docker Images ``` -docker pull ghcr.io/project-chip/chip-build-crosscompile:92 +docker pull ghcr.io/project-chip/chip-build-crosscompile:93 ``` ### Run docker ``` -docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:92 /bin/bash +docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:93 /bin/bash ``` ### Build diff --git a/examples/fabric-bridge-app/linux/README.md b/examples/fabric-bridge-app/linux/README.md index 75f510da97..b8f1b4a68b 100644 --- a/examples/fabric-bridge-app/linux/README.md +++ b/examples/fabric-bridge-app/linux/README.md @@ -100,13 +100,13 @@ defined: Pull Docker Images ``` - docker pull ghcr.io/project-chip/chip-build-crosscompile:92 + docker pull ghcr.io/project-chip/chip-build-crosscompile:93 ``` Run docker ``` - docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:92 /bin/bash + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:93 /bin/bash ``` Build diff --git a/examples/fabric-sync/README.md b/examples/fabric-sync/README.md index bf4a3b0627..2ef7949245 100644 --- a/examples/fabric-sync/README.md +++ b/examples/fabric-sync/README.md @@ -92,13 +92,13 @@ defined: Pull Docker Images ```sh - docker pull ghcr.io/project-chip/chip-build-crosscompile:92 + docker pull ghcr.io/project-chip/chip-build-crosscompile:93 ``` Run docker ```sh - docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:92 /bin/bash + docker run -it -v ~/connectedhomeip:/var/connectedhomeip ghcr.io/project-chip/chip-build-crosscompile:93 /bin/bash ``` Build diff --git a/examples/light-switch-app/ameba/README.md b/examples/light-switch-app/ameba/README.md index a499d29528..9df4fd6861 100644 --- a/examples/light-switch-app/ameba/README.md +++ b/examples/light-switch-app/ameba/README.md @@ -26,11 +26,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:92 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/lighting-app/ameba/README.md b/examples/lighting-app/ameba/README.md index ea6092575d..c4fe32b600 100644 --- a/examples/lighting-app/ameba/README.md +++ b/examples/lighting-app/ameba/README.md @@ -23,11 +23,11 @@ The CHIP demo application is supported on - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:92 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/ota-requestor-app/ameba/README.md b/examples/ota-requestor-app/ameba/README.md index 1f69815a78..c97609b7eb 100644 --- a/examples/ota-requestor-app/ameba/README.md +++ b/examples/ota-requestor-app/ameba/README.md @@ -6,11 +6,11 @@ A prototype application that demonstrates OTA Requestor capabilities. - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:92 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/examples/pigweed-app/ameba/README.md b/examples/pigweed-app/ameba/README.md index 66d7564c2c..1af7f58629 100644 --- a/examples/pigweed-app/ameba/README.md +++ b/examples/pigweed-app/ameba/README.md @@ -31,11 +31,11 @@ following features are available: - Pull docker image: - $ docker pull ghcr.io/project-chip/chip-build-ameba:92 + $ docker pull ghcr.io/project-chip/chip-build-ameba:93 - Run docker container: - $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:92 + $ docker run -it -v ${CHIP_DIR}:/root/chip ghcr.io/project-chip/chip-build-ameba:93 - Setup build environment: diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index eba19f43d5..238b47b0fc 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -23,7 +23,7 @@ steps: - name: pwenv path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" env: - PW_ENVIRONMENT_ROOT=/pwenv args: @@ -38,7 +38,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" env: - PW_ENVIRONMENT_ROOT=/pwenv args: diff --git a/integrations/cloudbuild/smoke-test.yaml b/integrations/cloudbuild/smoke-test.yaml index 22b3d377d8..41a221d048 100644 --- a/integrations/cloudbuild/smoke-test.yaml +++ b/integrations/cloudbuild/smoke-test.yaml @@ -1,5 +1,5 @@ steps: - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" entrypoint: "bash" args: - "-c" @@ -7,7 +7,7 @@ steps: git config --global --add safe.directory "*" python scripts/checkout_submodules.py --shallow --recursive --platform esp32 nrfconnect silabs linux android id: Submodules - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" # NOTE: silabs boostrap is NOT done with the rest as it requests a conflicting # jinja2 version (asks for 3.1.3 when constraints.txt asks for 3.0.3) env: @@ -24,7 +24,7 @@ steps: path: /pwenv timeout: 900s - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: ESP32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -45,7 +45,7 @@ steps: volumes: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: NRFConnect env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -66,7 +66,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: EFR32 env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -88,7 +88,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: Linux env: - PW_ENVIRONMENT_ROOT=/pwenv @@ -141,7 +141,7 @@ steps: - name: pwenv path: /pwenv - - name: "ghcr.io/project-chip/chip-build-vscode:92" + - name: "ghcr.io/project-chip/chip-build-vscode:93" id: Android env: - PW_ENVIRONMENT_ROOT=/pwenv diff --git a/src/platform/telink/CHIPDevicePlatformConfig.h b/src/platform/telink/CHIPDevicePlatformConfig.h index 3123d1464e..655ac12895 100644 --- a/src/platform/telink/CHIPDevicePlatformConfig.h +++ b/src/platform/telink/CHIPDevicePlatformConfig.h @@ -108,7 +108,7 @@ #define CHIP_DEVICE_CONFIG_ENABLE_ETHERNET 0 #endif // CHIP_DEVICE_CONFIG_ENABLE_ETHERNET -#ifdef CONFIG_SOC_RISCV_TELINK_TL321X +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) || defined(CONFIG_SOC_SERIES_RISCV_TELINK_B9X_RETENTION) #define CHIP_DEVICE_CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE (256) #define CHIP_DEVICE_CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE (256) #define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (256) diff --git a/src/platform/telink/SystemPlatformConfig.h b/src/platform/telink/SystemPlatformConfig.h index 462260e6d1..9f77a54b22 100644 --- a/src/platform/telink/SystemPlatformConfig.h +++ b/src/platform/telink/SystemPlatformConfig.h @@ -44,7 +44,7 @@ struct ChipDeviceEvent; #define CHIP_SYSTEM_CONFIG_PLATFORM_PROVIDES_TIME 1 #endif // CHIP_SYSTEM_CONFIG_USE_POSIX_TIME_FUNCTS -#ifdef CONFIG_SOC_RISCV_TELINK_TL321X +#if defined(CONFIG_SOC_RISCV_TELINK_TL321X) || defined(CONFIG_SOC_SERIES_RISCV_TELINK_B9X_RETENTION) #define CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_HEAP 1 #define CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL 0 #define CHIP_SYSTEM_CONFIG_POOL_USE_HEAP 1 From 60dd784ed76b6f67836f048e4b8ea3f89e3ea438 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Wed, 20 Nov 2024 11:11:48 -0500 Subject: [PATCH 057/219] Have `DataModel::Provider` be an argument to Server Init parameters (#36558) * Set a provider in server init * Restyle * Fix some include dependencies * Add back missing include * Undo change for nrf * Add import for android * Undo qpg change * Update examples/all-clusters-app/nrfconnect/main/AppTask.cpp Co-authored-by: Boris Zbarsky * Update examples/light-switch-app/qpg/src/AppTask.cpp Co-authored-by: Boris Zbarsky * Update examples/lock-app/nrfconnect/main/AppTask.cpp Co-authored-by: Boris Zbarsky * Update examples/lit-icd-app/nrfconnect/main/AppTask.cpp Co-authored-by: Boris Zbarsky * Update src/controller/python/chip/server/ServerInit.cpp Co-authored-by: Boris Zbarsky * Help users update * Added comment * Restyled by prettier-markdown * Update examples/lock-app/qpg/src/AppTask.cpp Co-authored-by: Boris Zbarsky * Update examples/platform/infineon/cyw30739/matter_config.cpp Co-authored-by: Boris Zbarsky * Update examples/platform/telink/common/src/AppTaskCommon.cpp Co-authored-by: Boris Zbarsky * Update examples/pump-app/nrfconnect/main/AppTask.cpp Co-authored-by: Boris Zbarsky * Update examples/platform/openiotsdk/app/openiotsdk_platform.cpp Co-authored-by: Boris Zbarsky * Fix includes * Removed an include * Update examples/pump-controller-app/nrfconnect/main/AppTask.cpp Co-authored-by: Boris Zbarsky * Update examples/shell/shell_common/cmd_server.cpp Co-authored-by: Boris Zbarsky * Update examples/window-app/nrfconnect/main/AppTask.cpp Co-authored-by: Boris Zbarsky * Remove extra include * More comments updated * Remove unneeded dependency * Fix log * Update src/app/server/Server.cpp Co-authored-by: Boris Zbarsky * Remove double init --------- Co-authored-by: Andrei Litvin Co-authored-by: Boris Zbarsky Co-authored-by: Restyled.io --- docs/upgrading.md | 9 +++++++++ .../ameba/main/chipinterface.cpp | 2 ++ .../air-purifier-app/cc32xx/main/AppTask.cpp | 2 ++ .../ameba/main/chipinterface.cpp | 2 ++ .../infineon/psoc6/src/AppTask.cpp | 2 ++ .../all-clusters-app/linux/fuzzing-main.cpp | 2 ++ .../all-clusters-app/mbed/main/AppTask.cpp | 3 ++- .../nrfconnect/main/AppTask.cpp | 2 ++ examples/all-clusters-app/nxp/mw320/main.cpp | 2 ++ .../ameba/main/chipinterface.cpp | 4 ++++ .../infineon/psoc6/src/AppTask.cpp | 2 ++ .../linux/fuzzing-main.cpp | 2 ++ .../mbed/main/AppTask.cpp | 6 ++++-- .../nrfconnect/main/AppTask.cpp | 2 ++ examples/chef/ameba/main/chipinterface.cpp | 5 +++++ examples/chef/esp32/main/main.cpp | 2 ++ examples/chef/nrfconnect/main.cpp | 4 +++- .../nxp/k32w0/main/AppTask.cpp | 2 ++ .../ameba/main/chipinterface.cpp | 2 ++ .../cc13x4_26x4/src/AppTask.cpp | 2 ++ .../light-switch-app/genio/src/AppTask.cpp | 2 ++ .../nrfconnect/main/AppTask.cpp | 2 ++ examples/light-switch-app/qpg/src/AppTask.cpp | 3 ++- .../lighting-app/ameba/main/chipinterface.cpp | 2 ++ .../lighting-app/cc13x4_26x4/src/AppTask.cpp | 2 ++ examples/lighting-app/genio/src/AppTask.cpp | 2 ++ .../infineon/psoc6/src/AppTask.cpp | 2 ++ examples/lighting-app/mbed/main/AppTask.cpp | 2 ++ .../lighting-app/nxp/k32w0/main/AppTask.cpp | 2 ++ .../stm32/src/STM32WB5/AppTask.cpp | 2 ++ .../lit-icd-app/nrfconnect/main/AppTask.cpp | 2 ++ examples/lock-app/cc13x4_26x4/src/AppTask.cpp | 2 ++ examples/lock-app/cc32xx/main/AppTask.cpp | 2 ++ examples/lock-app/genio/src/AppTask.cpp | 2 ++ .../lock-app/infineon/psoc6/src/AppTask.cpp | 2 ++ examples/lock-app/mbed/main/AppTask.cpp | 2 ++ examples/lock-app/nrfconnect/main/AppTask.cpp | 2 ++ .../lock-app/nxp/k32w/k32w0/main/AppTask.cpp | 2 ++ examples/lock-app/qpg/src/AppTask.cpp | 3 +++ examples/log-source-app/linux/main.cpp | 2 ++ .../ota-requestor-app/genio/src/AppTask.cpp | 2 ++ .../ota-requestor-app/mbed/main/AppTask.cpp | 2 ++ examples/platform/asr/init_Matter.cpp | 2 ++ .../platform/beken/common/BekenAppServer.cpp | 2 ++ .../bouffalolab/common/plat/platform.cpp | 2 ++ .../platform/esp32/common/Esp32AppServer.cpp | 2 ++ .../infineon/cyw30739/matter_config.cpp | 2 ++ examples/platform/linux/AppMain.cpp | 2 ++ examples/platform/linux/BUILD.gn | 1 + .../common/app_task/source/AppTaskBase.cpp | 2 ++ examples/platform/nxp/se05x/linux/AppMain.cpp | 2 ++ .../openiotsdk/app/openiotsdk_platform.cpp | 2 ++ examples/platform/silabs/MatterConfig.cpp | 2 ++ examples/platform/silabs/SiWx917/BUILD.gn | 1 + examples/platform/silabs/efr32/BUILD.gn | 1 + .../telink/common/src/AppTaskCommon.cpp | 2 ++ .../pump-app/cc13x4_26x4/main/AppTask.cpp | 2 ++ examples/pump-app/nrfconnect/main/AppTask.cpp | 2 ++ .../cc13x4_26x4/main/AppTask.cpp | 2 ++ .../nrfconnect/main/AppTask.cpp | 2 ++ examples/shell/cc13x4_26x4/main/AppTask.cpp | 2 ++ examples/shell/shell_common/cmd_server.cpp | 2 ++ examples/thermostat/genio/src/AppTask.cpp | 2 ++ examples/thermostat/qpg/src/AppTask.cpp | 2 ++ ...CommonCaseDeviceServerInitParamsProvider.h | 3 +++ examples/tv-casting-app/linux/main.cpp | 2 ++ examples/tv-casting-app/linux/simple-app.cpp | 2 ++ .../window-app/nrfconnect/main/AppTask.cpp | 2 ++ .../CodegenDataModelProvider.cpp | 1 + .../CodegenDataModelProvider.h | 2 +- src/app/server/Server.cpp | 20 +++++++++++++++++++ src/app/server/Server.h | 5 +++++ .../server/java/AndroidAppServerWrapper.cpp | 3 +++ src/app/server/java/BUILD.gn | 1 + .../tests/TestCommissioningWindowManager.cpp | 2 ++ src/app/util/mock/BUILD.gn | 1 + .../python/chip/server/ServerInit.cpp | 2 ++ 77 files changed, 186 insertions(+), 6 deletions(-) diff --git a/docs/upgrading.md b/docs/upgrading.md index 5640c925ac..de9ba38d23 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -92,3 +92,12 @@ Replacements for methods are: `chip::app::AttributeAccessInterfaceRegistry::Instance().UnregisterAllForEndpoint` - `chip::app::GetAttributeAccessOverride` replaced by `chip::app::AttributeAccessInterfaceRegistry::Instance().Get` + +### `ServerInitParams::dataModelProvider` in `Server::Init` + +Server initialization requires a set data model provider to work rather than +auto-initializing ember-compatible code-generated data models. + +To preserve `codegen/zap` generated logic, use +`CodegenDataModelProviderInstance` (see changes in +). diff --git a/examples/air-purifier-app/ameba/main/chipinterface.cpp b/examples/air-purifier-app/ameba/main/chipinterface.cpp index 34653db482..72563f987e 100644 --- a/examples/air-purifier-app/ameba/main/chipinterface.cpp +++ b/examples/air-purifier-app/ameba/main/chipinterface.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; diff --git a/examples/air-purifier-app/cc32xx/main/AppTask.cpp b/examples/air-purifier-app/cc32xx/main/AppTask.cpp index 0b284254b0..e7527ef338 100644 --- a/examples/air-purifier-app/cc32xx/main/AppTask.cpp +++ b/examples/air-purifier-app/cc32xx/main/AppTask.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -164,6 +165,7 @@ int AppTask::Init() PLAT_LOG("Initialize Server"); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/all-clusters-app/ameba/main/chipinterface.cpp b/examples/all-clusters-app/ameba/main/chipinterface.cpp index 7d06e72c09..06ba9f01cd 100644 --- a/examples/all-clusters-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-app/ameba/main/chipinterface.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -149,6 +150,7 @@ static void InitServer(intptr_t context) initParams.appDelegate = &sAmebaObserver; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); diff --git a/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp b/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp index bb499d2009..3b127091f1 100644 --- a/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/all-clusters-app/infineon/psoc6/src/AppTask.cpp @@ -25,6 +25,7 @@ #include "LEDWidget.h" #include #include +#include #include #include #include @@ -129,6 +130,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/all-clusters-app/linux/fuzzing-main.cpp b/examples/all-clusters-app/linux/fuzzing-main.cpp index 2d8422d0d2..5056f08cce 100644 --- a/examples/all-clusters-app/linux/fuzzing-main.cpp +++ b/examples/all-clusters-app/linux/fuzzing-main.cpp @@ -16,6 +16,7 @@ */ #include "AppMain.h" +#include #include #include @@ -56,6 +57,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) // ChipLinuxAppMainLoop blocks, and we don't want that here. static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); ApplicationInit(); diff --git a/examples/all-clusters-app/mbed/main/AppTask.cpp b/examples/all-clusters-app/mbed/main/AppTask.cpp index f67876b1da..98b8597ba4 100644 --- a/examples/all-clusters-app/mbed/main/AppTask.cpp +++ b/examples/all-clusters-app/mbed/main/AppTask.cpp @@ -72,7 +72,8 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - error = Server::GetInstance().Init(initParams); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Server initialization failed: %s", error.AsString()); diff --git a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp index 067e8113c4..9dcd423824 100644 --- a/examples/all-clusters-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-app/nrfconnect/main/AppTask.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -226,6 +227,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/all-clusters-app/nxp/mw320/main.cpp b/examples/all-clusters-app/nxp/mw320/main.cpp index 82d335cccb..bf0d6a282e 100644 --- a/examples/all-clusters-app/nxp/mw320/main.cpp +++ b/examples/all-clusters-app/nxp/mw320/main.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1068,6 +1069,7 @@ static void run_chip_srv(System::Layer * aSystemLayer, void * aAppState) static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); PRINTF("Done to call chip::Server() \r\n"); } diff --git a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp index 1fedda9583..cec1c457e0 100644 --- a/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp +++ b/examples/all-clusters-minimal-app/ameba/main/chipinterface.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -158,8 +159,11 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); + static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; + chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp b/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp index 56327c56dd..29ad68b742 100644 --- a/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/all-clusters-minimal-app/infineon/psoc6/src/AppTask.cpp @@ -25,6 +25,7 @@ #include "LEDWidget.h" #include #include +#include #include #include #include @@ -127,6 +128,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp b/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp index b1736826ef..ccd2ffa782 100644 --- a/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp +++ b/examples/all-clusters-minimal-app/linux/fuzzing-main.cpp @@ -16,6 +16,7 @@ */ #include "AppMain.h" +#include #include using namespace chip; @@ -43,6 +44,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t * aData, size_t aSize) // ChipLinuxAppMainLoop blocks, and we don't want that here. static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); VerifyOrDie(Server::GetInstance().Init(initParams) == CHIP_NO_ERROR); ApplicationInit(); diff --git a/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp b/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp index eb1188b93a..e516aee49e 100644 --- a/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/mbed/main/AppTask.cpp @@ -19,9 +19,10 @@ #include "AppTask.h" #include "LEDWidget.h" #include -#include +#include #include +#include #include #include #include @@ -67,7 +68,8 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); - error = Server::GetInstance().Init(initParams); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, "Server initialization failed: %s", error.AsString()); diff --git a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp index be858eae56..8d9771fa59 100644 --- a/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp +++ b/examples/all-clusters-minimal-app/nrfconnect/main/AppTask.cpp @@ -22,6 +22,7 @@ #include "LEDUtil.h" #include "binding-handler.h" +#include #include #include @@ -173,6 +174,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/chef/ameba/main/chipinterface.cpp b/examples/chef/ameba/main/chipinterface.cpp index ccdf43f3e5..6b772bdba6 100644 --- a/examples/chef/ameba/main/chipinterface.cpp +++ b/examples/chef/ameba/main/chipinterface.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -105,9 +106,13 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); + static AmebaObserver sAmebaObserver; initParams.appDelegate = &sAmebaObserver; + chip::Server::GetInstance().Init(initParams); + gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/chef/esp32/main/main.cpp b/examples/chef/esp32/main/main.cpp index b61fcf22bc..ef5dd73dca 100644 --- a/examples/chef/esp32/main/main.cpp +++ b/examples/chef/esp32/main/main.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -159,6 +160,7 @@ void InitServer(intptr_t) // Start IM server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Device Attestation & Onboarding codes diff --git a/examples/chef/nrfconnect/main.cpp b/examples/chef/nrfconnect/main.cpp index 1c7a3aa02a..e7e706409f 100644 --- a/examples/chef/nrfconnect/main.cpp +++ b/examples/chef/nrfconnect/main.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -125,7 +126,8 @@ int main() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); - err = chip::Server::GetInstance().Init(initParams); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); + err = chip::Server::GetInstance().Init(initParams); if (err != CHIP_NO_ERROR) { return 1; diff --git a/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp index 40ffd9d8bf..5eb7696fc6 100644 --- a/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp +++ b/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp @@ -18,6 +18,7 @@ */ #include "AppTask.h" #include "AppEvent.h" +#include #include #include #include @@ -298,6 +299,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/light-switch-app/ameba/main/chipinterface.cpp b/examples/light-switch-app/ameba/main/chipinterface.cpp index 31f285db45..84fd4f86e3 100644 --- a/examples/light-switch-app/ameba/main/chipinterface.cpp +++ b/examples/light-switch-app/ameba/main/chipinterface.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -104,6 +105,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; diff --git a/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp b/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp index 7dedcac647..3e2865b7b4 100644 --- a/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/light-switch-app/cc13x4_26x4/src/AppTask.cpp @@ -24,6 +24,7 @@ #include "FreeRTOS.h" +#include #include #include #include @@ -324,6 +325,7 @@ int AppTask::Init() static DefaultTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) }; initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); // Initialize info provider sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/light-switch-app/genio/src/AppTask.cpp b/examples/light-switch-app/genio/src/AppTask.cpp index f820d05ef1..ed331c5c1c 100644 --- a/examples/light-switch-app/genio/src/AppTask.cpp +++ b/examples/light-switch-app/genio/src/AppTask.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -124,6 +125,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/light-switch-app/nrfconnect/main/AppTask.cpp b/examples/light-switch-app/nrfconnect/main/AppTask.cpp index fc1c947150..c10da5aba9 100644 --- a/examples/light-switch-app/nrfconnect/main/AppTask.cpp +++ b/examples/light-switch-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -235,6 +236,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/light-switch-app/qpg/src/AppTask.cpp b/examples/light-switch-app/qpg/src/AppTask.cpp index 7cb0a41a45..2b1a49a51d 100644 --- a/examples/light-switch-app/qpg/src/AppTask.cpp +++ b/examples/light-switch-app/qpg/src/AppTask.cpp @@ -35,6 +35,7 @@ using namespace ::chip; #include #include #include +#include #include #include #include @@ -203,7 +204,6 @@ CHIP_ERROR AppTask::StartAppTask() void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; - (void) initParams.InitializeStaticResourcesBeforeServerInit(); gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -220,6 +220,7 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sFaultTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; chip::Server::GetInstance().Init(initParams); diff --git a/examples/lighting-app/ameba/main/chipinterface.cpp b/examples/lighting-app/ameba/main/chipinterface.cpp index d034fe0c1c..c98545110e 100644 --- a/examples/lighting-app/ameba/main/chipinterface.cpp +++ b/examples/lighting-app/ameba/main/chipinterface.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -124,6 +125,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CONFIG_ENABLE_AMEBA_CRYPTO ChipLogProgress(DeviceLayer, "platform crypto enabled!"); static chip::AmebaPersistentStorageOperationalKeystore sAmebaPersistentStorageOpKeystore; diff --git a/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp b/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp index 91aad59a9d..da48f6545d 100644 --- a/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/lighting-app/cc13x4_26x4/src/AppTask.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -315,6 +316,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); // Initialize info provider sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lighting-app/genio/src/AppTask.cpp b/examples/lighting-app/genio/src/AppTask.cpp index d948087833..b07d4ee3d9 100644 --- a/examples/lighting-app/genio/src/AppTask.cpp +++ b/examples/lighting-app/genio/src/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -324,6 +325,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/lighting-app/infineon/psoc6/src/AppTask.cpp b/examples/lighting-app/infineon/psoc6/src/AppTask.cpp index 43a501ad7e..0615b51188 100644 --- a/examples/lighting-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/lighting-app/infineon/psoc6/src/AppTask.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include /* OTA related includes */ @@ -143,6 +144,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); diff --git a/examples/lighting-app/mbed/main/AppTask.cpp b/examples/lighting-app/mbed/main/AppTask.cpp index 26403bdb5e..ce4d45a3aa 100644 --- a/examples/lighting-app/mbed/main/AppTask.cpp +++ b/examples/lighting-app/mbed/main/AppTask.cpp @@ -20,6 +20,7 @@ #include "LEDWidget.h" #include "LightingManager.h" +#include #include #include #include @@ -116,6 +117,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) diff --git a/examples/lighting-app/nxp/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w0/main/AppTask.cpp index 2418ab8597..191bfb9d0b 100644 --- a/examples/lighting-app/nxp/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w0/main/AppTask.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -282,6 +283,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp b/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp index 5841f15264..49649144b9 100644 --- a/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp +++ b/examples/lighting-app/stm32/src/STM32WB5/AppTask.cpp @@ -37,6 +37,7 @@ /*Matter includes*/ #include #include +#include #include #include #include @@ -152,6 +153,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); ReturnErrorOnFailure(mFactoryDataProvider.Init()); SetDeviceInstanceInfoProvider(&mFactoryDataProvider); SetCommissionableDataProvider(&mFactoryDataProvider); diff --git a/examples/lit-icd-app/nrfconnect/main/AppTask.cpp b/examples/lit-icd-app/nrfconnect/main/AppTask.cpp index 2fab2d91f8..6429473295 100644 --- a/examples/lit-icd-app/nrfconnect/main/AppTask.cpp +++ b/examples/lit-icd-app/nrfconnect/main/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -204,6 +205,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/lock-app/cc13x4_26x4/src/AppTask.cpp b/examples/lock-app/cc13x4_26x4/src/AppTask.cpp index 43d8f61ef1..fd99c0c0c6 100644 --- a/examples/lock-app/cc13x4_26x4/src/AppTask.cpp +++ b/examples/lock-app/cc13x4_26x4/src/AppTask.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -308,6 +309,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); // Initialize info provider sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lock-app/cc32xx/main/AppTask.cpp b/examples/lock-app/cc32xx/main/AppTask.cpp index 28c0675b8c..d610325b54 100644 --- a/examples/lock-app/cc32xx/main/AppTask.cpp +++ b/examples/lock-app/cc32xx/main/AppTask.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include @@ -151,6 +152,7 @@ int AppTask::Init() PLAT_LOG("Initialize Server"); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/lock-app/genio/src/AppTask.cpp b/examples/lock-app/genio/src/AppTask.cpp index 1c2f071979..fad169f910 100644 --- a/examples/lock-app/genio/src/AppTask.cpp +++ b/examples/lock-app/genio/src/AppTask.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/lock-app/infineon/psoc6/src/AppTask.cpp b/examples/lock-app/infineon/psoc6/src/AppTask.cpp index 54178c21c9..65ea49e769 100644 --- a/examples/lock-app/infineon/psoc6/src/AppTask.cpp +++ b/examples/lock-app/infineon/psoc6/src/AppTask.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -155,6 +156,7 @@ static void InitServer(intptr_t context) // Init ZCL Data Model static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); diff --git a/examples/lock-app/mbed/main/AppTask.cpp b/examples/lock-app/mbed/main/AppTask.cpp index 2dd5a4463d..bfa4ae73c0 100644 --- a/examples/lock-app/mbed/main/AppTask.cpp +++ b/examples/lock-app/mbed/main/AppTask.cpp @@ -20,6 +20,7 @@ #include "BoltLockManager.h" #include +#include #include #include #include @@ -119,6 +120,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) diff --git a/examples/lock-app/nrfconnect/main/AppTask.cpp b/examples/lock-app/nrfconnect/main/AppTask.cpp index 1025a04518..a495ca6833 100644 --- a/examples/lock-app/nrfconnect/main/AppTask.cpp +++ b/examples/lock-app/nrfconnect/main/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp index 5880a6e07c..14e7128791 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -191,6 +192,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); auto & infoProvider = chip::DeviceLayer::DeviceInfoProviderImpl::GetDefaultInstance(); infoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); diff --git a/examples/lock-app/qpg/src/AppTask.cpp b/examples/lock-app/qpg/src/AppTask.cpp index 8ae517dce2..74f6546f12 100644 --- a/examples/lock-app/qpg/src/AppTask.cpp +++ b/examples/lock-app/qpg/src/AppTask.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -202,6 +203,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); @@ -218,6 +220,7 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sFaultTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; chip::Server::GetInstance().Init(initParams); diff --git a/examples/log-source-app/linux/main.cpp b/examples/log-source-app/linux/main.cpp index d39e4431e8..fc46923f68 100644 --- a/examples/log-source-app/linux/main.cpp +++ b/examples/log-source-app/linux/main.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -105,6 +106,7 @@ int main(int argc, char * argv[]) chip::DeviceLayer::ConfigurationMgr().LogDeviceConfig(); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/ota-requestor-app/genio/src/AppTask.cpp b/examples/ota-requestor-app/genio/src/AppTask.cpp index ff78e703e4..424d7b20cb 100644 --- a/examples/ota-requestor-app/genio/src/AppTask.cpp +++ b/examples/ota-requestor-app/genio/src/AppTask.cpp @@ -18,6 +18,7 @@ */ #include #include +#include #include #include #include @@ -107,6 +108,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // We only have network commissioning on endpoint 0. diff --git a/examples/ota-requestor-app/mbed/main/AppTask.cpp b/examples/ota-requestor-app/mbed/main/AppTask.cpp index 0fa7df26f8..90436d5729 100644 --- a/examples/ota-requestor-app/mbed/main/AppTask.cpp +++ b/examples/ota-requestor-app/mbed/main/AppTask.cpp @@ -19,6 +19,7 @@ #include "AppTask.h" #include +#include #include #include #include @@ -106,6 +107,7 @@ int AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); error = Server::GetInstance().Init(initParams); if (error != CHIP_NO_ERROR) diff --git a/examples/platform/asr/init_Matter.cpp b/examples/platform/asr/init_Matter.cpp index a80fea5b4e..8280618c26 100644 --- a/examples/platform/asr/init_Matter.cpp +++ b/examples/platform/asr/init_Matter.cpp @@ -18,6 +18,7 @@ #include "AppConfig.h" #include +#include #include #include #include @@ -100,6 +101,7 @@ CHIP_ERROR MatterInitializer::Init_Matter_Server(void) chip::DeviceLayer::PlatformMgr().LockChipStack(); static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); chip::Server::GetInstance().Init(initParams); diff --git a/examples/platform/beken/common/BekenAppServer.cpp b/examples/platform/beken/common/BekenAppServer.cpp index 50f68cf441..7db9865381 100644 --- a/examples/platform/beken/common/BekenAppServer.cpp +++ b/examples/platform/beken/common/BekenAppServer.cpp @@ -19,6 +19,7 @@ #include "BekenAppServer.h" #include "CHIPDeviceManager.h" #include +#include #include #include #include @@ -38,6 +39,7 @@ void BekenAppServer::Init(AppDelegate * sAppDelegate) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); if (sAppDelegate != nullptr) { initParams.appDelegate = sAppDelegate; diff --git a/examples/platform/bouffalolab/common/plat/platform.cpp b/examples/platform/bouffalolab/common/plat/platform.cpp index 6a91567ab9..723df8fa0d 100644 --- a/examples/platform/bouffalolab/common/plat/platform.cpp +++ b/examples/platform/bouffalolab/common/plat/platform.cpp @@ -17,6 +17,7 @@ */ #include #include +#include #include #include #include @@ -245,6 +246,7 @@ CHIP_ERROR PlatformManagerImpl::PlatformInit(void) static CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); #if CHIP_DEVICE_CONFIG_ENABLE_THREAD chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; diff --git a/examples/platform/esp32/common/Esp32AppServer.cpp b/examples/platform/esp32/common/Esp32AppServer.cpp index 8740f39cdb..e05817bfe0 100644 --- a/examples/platform/esp32/common/Esp32AppServer.cpp +++ b/examples/platform/esp32/common/Esp32AppServer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,7 @@ void Esp32AppServer::Init(AppDelegate * sAppDelegate) initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; #endif // CONFIG_TEST_EVENT_TRIGGER_ENABLED && CONFIG_ENABLE_OTA_REQUESTOR (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); if (sAppDelegate != nullptr) { initParams.appDelegate = sAppDelegate; diff --git a/examples/platform/infineon/cyw30739/matter_config.cpp b/examples/platform/infineon/cyw30739/matter_config.cpp index c30d55e55b..42bc9f3d1d 100644 --- a/examples/platform/infineon/cyw30739/matter_config.cpp +++ b/examples/platform/infineon/cyw30739/matter_config.cpp @@ -37,6 +37,7 @@ #include "wiced_hal_i2c.h" #endif #include +#include #include #include #include @@ -216,6 +217,7 @@ void CYW30739MatterConfig::InitApp(void) // Create initParams with SDK example defaults here static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; sExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); SetDeviceInfoProvider(&sExampleDeviceInfoProvider); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index e3b68e319e..ddd4d82420 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -532,6 +533,7 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 30583ce7d0..5b5d307e41 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -95,6 +95,7 @@ source_set("app-main") { ":energy-reporting-test-event-trigger", ":smco-test-event-trigger", ":water-heater-management-test-event-trigger", + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/controller:controller", "${chip_root}/src/controller:gen_check_chip_controller_headers", "${chip_root}/src/lib", diff --git a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp index 81907d2163..00ccbb9ea3 100644 --- a/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp +++ b/examples/platform/nxp/common/app_task/source/AppTaskBase.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -185,6 +186,7 @@ void chip::NXP::App::AppTaskBase::InitServer(intptr_t arg) initParams.operationalKeystore = chip::NXP::App::OperationalKeystore::GetInstance(); #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if CONFIG_NET_L2_OPENTHREAD // Init ZCL Data Model and start server diff --git a/examples/platform/nxp/se05x/linux/AppMain.cpp b/examples/platform/nxp/se05x/linux/AppMain.cpp index bd13e24968..5baf36112b 100644 --- a/examples/platform/nxp/se05x/linux/AppMain.cpp +++ b/examples/platform/nxp/se05x/linux/AppMain.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -291,6 +292,7 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(initParams.InitializeStaticResourcesBeforeServerInit() == CHIP_NO_ERROR); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); diff --git a/examples/platform/openiotsdk/app/openiotsdk_platform.cpp b/examples/platform/openiotsdk/app/openiotsdk_platform.cpp index 56bb7c2490..705f35e86b 100644 --- a/examples/platform/openiotsdk/app/openiotsdk_platform.cpp +++ b/examples/platform/openiotsdk/app/openiotsdk_platform.cpp @@ -42,6 +42,7 @@ #include #ifdef USE_CHIP_DATA_MODEL +#include #include #include #include @@ -274,6 +275,7 @@ int openiotsdk_chip_run(void) ChipLogError(NotSpecified, "Initialize static resources before server init failed: %s", err.AsString()); return EXIT_FAILURE; } + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.operationalServicePort = CHIP_PORT; initParams.userDirectedCommissioningPort = CHIP_UDC_PORT; diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 8c0488f74c..c382a3ab1a 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -56,6 +56,7 @@ static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeys #include #include #include +#include #ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED #include "SilabsTestEventTriggerDelegate.h" // nogncheck @@ -275,6 +276,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) // Initialize the remaining (not overridden) providers to the SDK example defaults (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); #if CHIP_ENABLE_OPENTHREAD // Set up OpenThread configuration when OpenThread is included diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 2d6d3574ea..02769a993c 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -189,6 +189,7 @@ source_set("siwx917-common") { public_deps += [ "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", ] diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index e0e7b45070..7b9dccf7cc 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -214,6 +214,7 @@ source_set("efr32-common") { public_deps += [ "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/app/server", "${chip_root}/src/lib", "${chip_root}/src/setup_payload", diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp index de5faa974a..479e746a4a 100644 --- a/examples/platform/telink/common/src/AppTaskCommon.cpp +++ b/examples/platform/telink/common/src/AppTaskCommon.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -301,6 +302,7 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void) VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.appDelegate = &sCallbacks; initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); diff --git a/examples/pump-app/cc13x4_26x4/main/AppTask.cpp b/examples/pump-app/cc13x4_26x4/main/AppTask.cpp index 0a7d6a2600..bb5e212eee 100644 --- a/examples/pump-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/pump-app/cc13x4_26x4/main/AppTask.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -309,6 +310,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); diff --git a/examples/pump-app/nrfconnect/main/AppTask.cpp b/examples/pump-app/nrfconnect/main/AppTask.cpp index d5f4c6dc76..f8939268f3 100644 --- a/examples/pump-app/nrfconnect/main/AppTask.cpp +++ b/examples/pump-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -205,6 +206,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp b/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp index ac7eb545a1..0a8de126a1 100644 --- a/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp +++ b/examples/pump-controller-app/cc13x4_26x4/main/AppTask.cpp @@ -38,6 +38,7 @@ #endif #include #include +#include #include #include #include @@ -301,6 +302,7 @@ int AppTask::Init() initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); ret = PlatformMgr().StartEventLoopTask(); diff --git a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp index ca79a41160..eb4d194d2f 100644 --- a/examples/pump-controller-app/nrfconnect/main/AppTask.cpp +++ b/examples/pump-controller-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,7 @@ CHIP_ERROR AppTask::Init() VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/shell/cc13x4_26x4/main/AppTask.cpp b/examples/shell/cc13x4_26x4/main/AppTask.cpp index 3f5ff1e659..cc6122cef0 100644 --- a/examples/shell/cc13x4_26x4/main/AppTask.cpp +++ b/examples/shell/cc13x4_26x4/main/AppTask.cpp @@ -22,6 +22,7 @@ #include "FreeRTOS.h" +#include #include #include #include @@ -161,6 +162,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); ret = PlatformMgr().StartEventLoopTask(); diff --git a/examples/shell/shell_common/cmd_server.cpp b/examples/shell/shell_common/cmd_server.cpp index 6c79aae789..80884b9c04 100644 --- a/examples/shell/shell_common/cmd_server.cpp +++ b/examples/shell/shell_common/cmd_server.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,7 @@ static CHIP_ERROR CmdAppServerStart(int argc, char ** argv) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.operationalServicePort = sServerPortOperational; initParams.userDirectedCommissioningPort = sServerPortCommissioning; diff --git a/examples/thermostat/genio/src/AppTask.cpp b/examples/thermostat/genio/src/AppTask.cpp index ac419e01f5..3733b7f459 100644 --- a/examples/thermostat/genio/src/AppTask.cpp +++ b/examples/thermostat/genio/src/AppTask.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -123,6 +124,7 @@ CHIP_ERROR AppTask::Init() // Init ZCL Data Model and start server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/thermostat/qpg/src/AppTask.cpp b/examples/thermostat/qpg/src/AppTask.cpp index 306661766a..f91db8b689 100644 --- a/examples/thermostat/qpg/src/AppTask.cpp +++ b/examples/thermostat/qpg/src/AppTask.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -173,6 +174,7 @@ void AppTask::InitServer(intptr_t arg) { static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h index d510a0ec48..93b4edc783 100644 --- a/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h +++ b/examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/MCCommonCaseDeviceServerInitParamsProvider.h @@ -17,6 +17,8 @@ #include "core/Types.h" +#include + #ifndef MCCommonCaseDeviceServerInitParamsProvider_h #define MCCommonCaseDeviceServerInitParamsProvider_h @@ -35,6 +37,7 @@ class MCCommonCaseDeviceServerInitParamsProvider : public matter::casting::suppo CHIP_ERROR err = serverInitParams.InitializeStaticResourcesBeforeServerInit(); VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(AppServer, "Initialization of ServerInitParams failed %" CHIP_ERROR_FORMAT, err.Format())); + serverInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); return &serverInitParams; } }; diff --git a/examples/tv-casting-app/linux/main.cpp b/examples/tv-casting-app/linux/main.cpp index 0dde8a2f0d..3a41f15d53 100644 --- a/examples/tv-casting-app/linux/main.cpp +++ b/examples/tv-casting-app/linux/main.cpp @@ -31,6 +31,7 @@ #include "LinuxCommissionableDataProvider.h" #include "Options.h" +#include #include #include #include @@ -140,6 +141,7 @@ int main(int argc, char * argv[]) // Enter commissioning mode, open commissioning window static chip::CommonCaseDeviceServerInitParams initParams; VerifyOrDie(CHIP_NO_ERROR == initParams.InitializeStaticResourcesBeforeServerInit()); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); VerifyOrDie(CHIP_NO_ERROR == chip::Server::GetInstance().Init(initParams)); if (argc > 1) diff --git a/examples/tv-casting-app/linux/simple-app.cpp b/examples/tv-casting-app/linux/simple-app.cpp index 41f3391da7..5526d6a3f6 100644 --- a/examples/tv-casting-app/linux/simple-app.cpp +++ b/examples/tv-casting-app/linux/simple-app.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -83,6 +84,7 @@ class CommonCaseDeviceServerInitParamsProvider : public ServerInitParamsProvider CHIP_ERROR err = serverInitParams.InitializeStaticResourcesBeforeServerInit(); VerifyOrReturnValue(err == CHIP_NO_ERROR, nullptr, ChipLogError(AppServer, "Initialization of ServerInitParams failed %" CHIP_ERROR_FORMAT, err.Format())); + serverInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); return &serverInitParams; } }; diff --git a/examples/window-app/nrfconnect/main/AppTask.cpp b/examples/window-app/nrfconnect/main/AppTask.cpp index 5f971b67f9..21438b76e9 100644 --- a/examples/window-app/nrfconnect/main/AppTask.cpp +++ b/examples/window-app/nrfconnect/main/AppTask.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index 3e5e3a8cf0..b0815da48e 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h index 7549ef1fd4..59b91747a0 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h @@ -16,10 +16,10 @@ */ #pragma once -#include "app/ConcreteCommandPath.h" #include #include +#include #include #include diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 6808431b67..e9475fdbf9 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -127,6 +127,15 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) VerifyOrExit(initParams.opCertStore != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(initParams.reportScheduler != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + // Extra log since this is an incremental requirement and existing applications may not be aware + if (initParams.dataModelProvider == nullptr) + { + ChipLogError(AppServer, "Application Server requires a `initParams.dataModelProvider` value."); + ChipLogError(AppServer, "For backwards compatibility, you likely can use `CodegenDataModelProviderInstance()`"); + } + + VerifyOrExit(initParams.dataModelProvider != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); + // TODO(16969): Remove chip::Platform::MemoryInit() call from Server class, it belongs to outer code chip::Platform::MemoryInit(); @@ -161,6 +170,17 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) SetAttributePersistenceProvider(&mAttributePersister); SetSafeAttributePersistenceProvider(&mAttributePersister); + // SetDataModelProvider() actually initializes/starts the provider. We need + // to preserve the following ordering guarantees: + // + // 1) Provider initialization (under SetDataModelProvider) happens after + // SetSafeAttributePersistenceProvider, since the provider can then use + // the safe persistence provider to implement and initialize its own attribute persistence logic. + // 2) For now, provider initialization happens before InitDataModelHandler(), which depends + // on atttribute persistence being already set up before it runs. Longer-term, the logic from + // InitDataModelHandler should just move into the codegen provider. + chip::app::InteractionModelEngine::GetInstance()->SetDataModelProvider(initParams.dataModelProvider); + { FabricTable::InitParams fabricTableInitParams; fabricTableInitParams.storage = mDeviceStorage; diff --git a/src/app/server/Server.h b/src/app/server/Server.h index fc6f7ac107..5c5068d790 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -192,6 +192,11 @@ struct ServerInitParams // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy. app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr; #endif // CHIP_CONFIG_ENABLE_ICD_CIP + + // MUST NOT be null during initialization: every application must define the + // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance` + // for ember/zap-generated models. + chip::app::DataModel::Provider * dataModelProvider = nullptr; }; /** diff --git a/src/app/server/java/AndroidAppServerWrapper.cpp b/src/app/server/java/AndroidAppServerWrapper.cpp index 69436b1764..5e205b7d82 100644 --- a/src/app/server/java/AndroidAppServerWrapper.cpp +++ b/src/app/server/java/AndroidAppServerWrapper.cpp @@ -17,6 +17,8 @@ */ #include "AndroidAppServerWrapper.h" + +#include #include #include #include @@ -50,6 +52,7 @@ CHIP_ERROR ChipAndroidAppInit(AppDelegate * appDelegate) // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); if (appDelegate != nullptr) { initParams.appDelegate = appDelegate; diff --git a/src/app/server/java/BUILD.gn b/src/app/server/java/BUILD.gn index c25548eb11..98012409b1 100644 --- a/src/app/server/java/BUILD.gn +++ b/src/app/server/java/BUILD.gn @@ -36,6 +36,7 @@ static_library("jni") { ] deps = [ + "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/app/server", "${chip_root}/src/inet", "${chip_root}/src/lib", diff --git a/src/app/tests/TestCommissioningWindowManager.cpp b/src/app/tests/TestCommissioningWindowManager.cpp index 297a95e299..7a2e127324 100644 --- a/src/app/tests/TestCommissioningWindowManager.cpp +++ b/src/app/tests/TestCommissioningWindowManager.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -113,6 +114,7 @@ class TestCommissioningWindowManager : public ::testing::Test static chip::SimpleTestEventTriggerDelegate sSimpleTestEventTriggerDelegate; initParams.testEventTriggerDelegate = &sSimpleTestEventTriggerDelegate; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Use whatever server port the kernel decides to give us. initParams.operationalServicePort = 0; diff --git a/src/app/util/mock/BUILD.gn b/src/app/util/mock/BUILD.gn index db566aad57..0b99d82740 100644 --- a/src/app/util/mock/BUILD.gn +++ b/src/app/util/mock/BUILD.gn @@ -56,4 +56,5 @@ source_set("mock_codegen_data_model") { public_configs = [ ":mock_include" ] public_deps += [ ":mock_ember" ] + deps = [ "${chip_root}/src/app/util/persistence:persistence" ] } diff --git a/src/controller/python/chip/server/ServerInit.cpp b/src/controller/python/chip/server/ServerInit.cpp index 39edd7a2ad..83bb8acefe 100644 --- a/src/controller/python/chip/server/ServerInit.cpp +++ b/src/controller/python/chip/server/ServerInit.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -161,6 +162,7 @@ PyChipError pychip_server_native_init() // Init ZCL Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; PyReturnErrorOnFailure(ToPyChipError(initParams.InitializeStaticResourcesBeforeServerInit())); + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); initParams.operationalServicePort = CHIP_PORT; initParams.userDirectedCommissioningPort = CHIP_UDC_PORT; From e1fbaf6fd151e739599e51076594f2dc35696fe9 Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Wed, 20 Nov 2024 12:39:52 -0500 Subject: [PATCH 058/219] TC_WHM_2_1: Fix incorrect --aplication argument (#36578) It should be `water-heater` instead of `evse`. --- src/python_testing/TC_WHM_2_1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_testing/TC_WHM_2_1.py b/src/python_testing/TC_WHM_2_1.py index b9dcb0257d..538450e598 100644 --- a/src/python_testing/TC_WHM_2_1.py +++ b/src/python_testing/TC_WHM_2_1.py @@ -26,7 +26,7 @@ # --discriminator 1234 # --KVS kvs1 # --trace-to json:${TRACE_APP}.json -# --application evse +# --application water-heater # script-args: > # --storage-path admin_storage.json # --commissioning-method on-network From 90f96caeeb8f0cf525e2216d8736527898f5669d Mon Sep 17 00:00:00 2001 From: Michael Rupp <95718139+mykrupp@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:44:26 -0500 Subject: [PATCH 059/219] use VerifyOrDie instead of assert() (#36583) --- examples/platform/silabs/MatterShell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/platform/silabs/MatterShell.cpp b/examples/platform/silabs/MatterShell.cpp index 6088eeb2ca..38f97385bb 100644 --- a/examples/platform/silabs/MatterShell.cpp +++ b/examples/platform/silabs/MatterShell.cpp @@ -114,7 +114,7 @@ void cmdSilabsInit() void startShellTask() { int status = chip::Shell::Engine::Root().Init(); - assert(status == 0); + VerifyOrDie(status == 0); // For now also register commands from shell_common (shell app). // TODO move at least OTCLI to default commands in lib/shell/commands From 334b1d9fe325e442393c3c861268ab5310a55198 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 20 Nov 2024 19:22:27 -0500 Subject: [PATCH 060/219] Improve logging in setPersistedClusterData. (#36581) Before this change we would log setPersistedClusterData claiming we don't know our VID/PID/etc, though chances are the data being passed in exactly contains that information. In the new setup, we update our state, then log. --- src/darwin/Framework/CHIP/MTRDevice_Concrete.mm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 35cfbcf7d8..0fa798e8fa 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -3799,7 +3799,14 @@ - (NSUInteger)unitTestAttributeCount - (void)setPersistedClusterData:(NSDictionary *)clusterData { + [self _doSetPersistedClusterData:clusterData]; + + // Log after we do the state update, so the log includes the data we just set. MTR_LOG("%@ setPersistedClusterData count: %lu", self, static_cast(clusterData.count)); +} + +- (void)_doSetPersistedClusterData:(NSDictionary *)clusterData +{ if (!clusterData.count) { return; } From 709841e4a766b368b655b82871edee058a33eea9 Mon Sep 17 00:00:00 2001 From: Justin Wood Date: Wed, 20 Nov 2024 23:00:59 -0800 Subject: [PATCH 061/219] If an XPC client doesn't care about a nodeID (hasn't made it), don't create one (#36586) * Fixing infinite loop * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/darwin/Framework/CHIP/MTRDeviceController.mm | 9 +++++++-- src/darwin/Framework/CHIP/MTRDeviceController_Internal.h | 1 + src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 5cee77cb66..8bbad10886 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -371,17 +371,22 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N return [[MTRDevice alloc] initForSubclassesWithNodeID:nodeID controller:self]; } -- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID +- (MTRDevice *)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded { std::lock_guard lock(*self.deviceMapLock); MTRDevice * deviceToReturn = [_nodeIDToDeviceMap objectForKey:nodeID]; - if (!deviceToReturn) { + if (!deviceToReturn && createIfNeeded) { deviceToReturn = [self _setupDeviceForNodeID:nodeID prefetchedClusterData:nil]; } return deviceToReturn; } +- (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID +{ + return [self _deviceForNodeID:nodeID createIfNeeded:YES]; +} + - (void)removeDevice:(MTRDevice *)device { std::lock_guard lock(*self.deviceMapLock); diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h index 8fc93b6235..ed5e870adc 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h @@ -107,6 +107,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Device-specific data and SDK access // DeviceController will act as a central repository for this opaque dictionary that MTRDevice manages - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID; +- (MTRDevice *)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded; /** * _setupDeviceForNodeID is a hook expected to be implemented by subclasses to * actually allocate a device object of the right type. diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm b/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm index 9b9a87bb97..827dad5260 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController_XPC.mm @@ -487,7 +487,7 @@ - (oneway void)controller:(NSUUID *)controller controllerConfigurationUpdated:(N continue; } - auto * device = static_cast([self deviceForNodeID:nodeID]); + auto * device = static_cast([self _deviceForNodeID:nodeID createIfNeeded:NO]); [device device:nodeID internalStateUpdated:deviceInternalState]; } } From 2439117dec8f4f05756a0c4bc3af7d4f733d612f Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Thu, 21 Nov 2024 16:40:23 +0530 Subject: [PATCH 062/219] ESP32: fix typo to include correct Span.h in secure cert data provider (#36589) * ESP32: fix typo to include correct Span.h in secure cert data provider * restyle --- src/platform/ESP32/ESP32SecureCertDataProvider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/ESP32/ESP32SecureCertDataProvider.cpp b/src/platform/ESP32/ESP32SecureCertDataProvider.cpp index e3bb02155b..c464c07c65 100644 --- a/src/platform/ESP32/ESP32SecureCertDataProvider.cpp +++ b/src/platform/ESP32/ESP32SecureCertDataProvider.cpp @@ -21,8 +21,8 @@ #include #include +#include #include -#include #include namespace chip { From 13920e56451b7881a74607c3e5b0d6937dee28de Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Thu, 21 Nov 2024 18:00:44 +0100 Subject: [PATCH 063/219] [Linux] Fix crash when shutting down BLE Manager after platform shutdown (#36550) --- src/platform/Linux/bluez/BluezObjectManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform/Linux/bluez/BluezObjectManager.cpp b/src/platform/Linux/bluez/BluezObjectManager.cpp index 2d555edc56..3a694dd646 100644 --- a/src/platform/Linux/bluez/BluezObjectManager.cpp +++ b/src/platform/Linux/bluez/BluezObjectManager.cpp @@ -62,6 +62,11 @@ CHIP_ERROR BluezObjectManager::Init() void BluezObjectManager::Shutdown() { + // If the D-Bus connection or the object manager are not initialized, + // there is nothing to shutdown. This check prevents unnecessary call + // to the GLibMatterContextInvokeSync function. + VerifyOrReturn(mConnection || mObjectManager); + // Run endpoint cleanup on the CHIPoBluez thread. This is necessary because the // cleanup function releases the D-Bus manager client object, which handles D-Bus // signals. Otherwise, we will face race condition when the D-Bus signal is in From 093aff824ccd4cc02ed5cddd85c7635ef5c46fb4 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Thu, 21 Nov 2024 18:01:43 +0100 Subject: [PATCH 064/219] [Linux] Reuse short UUID defined in BLE layer (#36557) * [Linux] Reuse short UUID defined in BLE layer * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/platform/Linux/BLEManagerImpl.cpp | 7 +++---- src/platform/Linux/BLEManagerImpl.h | 1 - src/platform/NuttX/BLEManagerImpl.cpp | 9 ++++----- src/platform/NuttX/BLEManagerImpl.h | 1 - 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 4ef45f88ea..9f285e6192 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -186,9 +186,8 @@ uint16_t BLEManagerImpl::_NumConnections() CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) { - mAdapterId = aAdapterId; - mIsCentral = aIsCentral; - mpBLEAdvUUID = "0xFFF6"; + mAdapterId = aAdapterId; + mIsCentral = aIsCentral; return CHIP_NO_ERROR; } @@ -578,7 +577,7 @@ void BLEManagerImpl::DriveBLEState() // Configure advertising data if it hasn't been done yet. if (!mFlags.Has(Flags::kAdvertisingConfigured)) { - SuccessOrExit(err = mBLEAdvertisement.Init(mAdapter.get(), mpBLEAdvUUID, mDeviceName)); + SuccessOrExit(err = mBLEAdvertisement.Init(mAdapter.get(), Ble::CHIP_BLE_SERVICE_SHORT_UUID_STR, mDeviceName)); mFlags.Set(Flags::kAdvertisingConfigured); } diff --git a/src/platform/Linux/BLEManagerImpl.h b/src/platform/Linux/BLEManagerImpl.h index e216a09b8e..d4aeaa3b89 100644 --- a/src/platform/Linux/BLEManagerImpl.h +++ b/src/platform/Linux/BLEManagerImpl.h @@ -199,7 +199,6 @@ class BLEManagerImpl final : public BLEManager, BluezEndpoint mEndpoint{ mBluezObjectManager }; BluezAdvertisement mBLEAdvertisement{ mEndpoint }; - const char * mpBLEAdvUUID = nullptr; ChipDeviceScanner mDeviceScanner{ mBluezObjectManager }; BLEScanConfig mBLEScanConfig; diff --git a/src/platform/NuttX/BLEManagerImpl.cpp b/src/platform/NuttX/BLEManagerImpl.cpp index 6672b5d4bd..b8d7c64d00 100644 --- a/src/platform/NuttX/BLEManagerImpl.cpp +++ b/src/platform/NuttX/BLEManagerImpl.cpp @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include @@ -197,9 +197,8 @@ uint16_t BLEManagerImpl::_NumConnections() CHIP_ERROR BLEManagerImpl::ConfigureBle(uint32_t aAdapterId, bool aIsCentral) { - mAdapterId = aAdapterId; - mIsCentral = aIsCentral; - mpBLEAdvUUID = "0xFFF6"; + mAdapterId = aAdapterId; + mIsCentral = aIsCentral; return CHIP_NO_ERROR; } @@ -587,7 +586,7 @@ void BLEManagerImpl::DriveBLEState() // Configure advertising data if it hasn't been done yet. if (!mFlags.Has(Flags::kAdvertisingConfigured)) { - SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, mpBLEAdvUUID, mDeviceName)); + SuccessOrExit(err = mBLEAdvertisement.Init(mEndpoint, Ble::CHIP_BLE_SERVICE_SHORT_UUID_STR, mDeviceName)); mFlags.Set(Flags::kAdvertisingConfigured); } diff --git a/src/platform/NuttX/BLEManagerImpl.h b/src/platform/NuttX/BLEManagerImpl.h index f6f6db6c3a..e8aca8b7c7 100644 --- a/src/platform/NuttX/BLEManagerImpl.h +++ b/src/platform/NuttX/BLEManagerImpl.h @@ -189,7 +189,6 @@ class BLEManagerImpl final : public BLEManager, BluezEndpoint mEndpoint; BluezAdvertisement mBLEAdvertisement; - const char * mpBLEAdvUUID = nullptr; ChipDeviceScanner mDeviceScanner; BLEScanConfig mBLEScanConfig; From ab838ddba7f278f12568e2f0d2027a49ebeebc8d Mon Sep 17 00:00:00 2001 From: Terence Hampson Date: Thu, 21 Nov 2024 15:53:09 -0500 Subject: [PATCH 065/219] Add pigweed.json to root and opt out to cli analytics (#36598) --- pigweed.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 pigweed.json diff --git a/pigweed.json b/pigweed.json new file mode 100644 index 0000000000..aef11e7a51 --- /dev/null +++ b/pigweed.json @@ -0,0 +1,7 @@ +{ + "pw": { + "pw_cli_analytics": { + "enabled": false + } + } +} From e6340400b74017888dd0bb4583b60427aa3f5fe6 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 21 Nov 2024 20:59:17 -0500 Subject: [PATCH 066/219] Better logging when Darwin.framework is asked to encode an incorrect type in a list. (#36599) --- .../CHIP/templates/MTRBaseClusters-src.zapt | 1 + .../templates/MTRCommandPayloadsObjc-src.zapt | 1 + .../CHIP/templates/partials/encode_value.zapt | 5 +- .../CHIP/zap-generated/MTRBaseClusters.mm | 111 ++++--- .../zap-generated/MTRCommandPayloadsObjc.mm | 296 +++++++++++------- 5 files changed, 250 insertions(+), 164 deletions(-) diff --git a/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt b/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt index 0b8529b9c5..f90acdd4fd 100644 --- a/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRBaseClusters-src.zapt @@ -9,6 +9,7 @@ #import "MTRClusterStateCacheContainer_Internal.h" #import "MTRCommandPayloadsObjc.h" #import "MTRDevice_Internal.h" +#import "MTRLogging_Internal.h" #import "MTRStructsObjc.h" #import "NSStringSpanConversion.h" #import "NSDataSpanConversion.h" diff --git a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt index 4179d5a905..41af262e03 100644 --- a/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt +++ b/src/darwin/Framework/CHIP/templates/MTRCommandPayloadsObjc-src.zapt @@ -4,6 +4,7 @@ #import "MTRCommandPayloads_Internal.h" #import "MTRCommandPayloadExtensions_Internal.h" #import "MTRBaseDevice_Internal.h" +#import "MTRDefines_Internal.h" #import "MTRError_Internal.h" #import "MTRLogging_Internal.h" #import "NSStringSpanConversion.h" diff --git a/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt b/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt index f2f4d076b7..16e2b3e123 100644 --- a/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt +++ b/src/darwin/Framework/CHIP/templates/partials/encode_value.zapt @@ -27,11 +27,12 @@ } listFreer.add(listHolder_{{depth}}); for (size_t i_{{depth}} = 0; i_{{depth}} < {{source}}.count; ++i_{{depth}}) { - if ( ! [{{source}}[i_{{depth}}] isKindOfClass: [{{asObjectiveCClass type cluster forceNotList=true}} class]] ) { + auto element_{{depth}} = MTR_SAFE_CAST({{source}}[i_{{depth}}], {{asObjectiveCClass type cluster forceNotList=true}}); + if (!element_{{depth}}) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", {{source}}[i_{{depth}}], NSStringFromClass({{asObjectiveCClass type cluster forceNotList=true}}.class)); {{errorCode}} } - auto element_{{depth}} = ({{asObjectiveCClass type cluster forceNotList=true}} *){{source}}[i_{{depth}}]; {{>encode_value target=(concat "listHolder_" depth "->mList[i_" depth "]") source=(concat "element_" depth) cluster=cluster errorCode=errorCode depth=(incrementDepth depth) isArray=false}} } {{target}} = ListType_{{depth}}(listHolder_{{depth}}->mList, {{source}}.count); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index ea02951aa5..47d9cb1415 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -25,6 +25,7 @@ #import "MTRCommandPayloadsObjc.h" #import "MTRDefines_Internal.h" #import "MTRDevice_Internal.h" +#import "MTRLogging_Internal.h" #import "MTRStructsObjc.h" #import "NSDataSpanConversion.h" #import "NSStringSpanConversion.h" @@ -5173,11 +5174,12 @@ - (void)writeAttributeBindingWithValue:(NSArray * _Nonnull)value params:(MTRWrit } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRBindingClusterTargetStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRBindingClusterTargetStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRBindingClusterTargetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRBindingClusterTargetStruct *)value[i_0]; if (element_0.node != nil) { auto & definedValue_2 = listHolder_0->mList[i_0].node.Emplace(); definedValue_2 = element_0.node.unsignedLongLongValue; @@ -5712,11 +5714,12 @@ - (void)writeAttributeACLWithValue:(NSArray * _Nonnull)value params:(MTRWritePar } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRAccessControlClusterAccessControlEntryStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRAccessControlClusterAccessControlEntryStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRAccessControlClusterAccessControlEntryStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRAccessControlClusterAccessControlEntryStruct *)value[i_0]; listHolder_0->mList[i_0].privilege = static_castmList[i_0].privilege)>>(element_0.privilege.unsignedCharValue); listHolder_0->mList[i_0].authMode = static_castmList[i_0].authMode)>>(element_0.authMode.unsignedCharValue); if (element_0.subjects == nil) { @@ -5733,11 +5736,12 @@ - (void)writeAttributeACLWithValue:(NSArray * _Nonnull)value params:(MTRWritePar } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.subjects.count; ++i_3) { - if ( ! [element_0.subjects[i_3] isKindOfClass: [NSNumber class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.subjects[i_3], NSNumber); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.subjects[i_3], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSNumber *)element_0.subjects[i_3]; listHolder_3->mList[i_3] = element_3.unsignedLongLongValue; } nonNullValue_2 = ListType_3(listHolder_3->mList, element_0.subjects.count); @@ -5760,11 +5764,12 @@ - (void)writeAttributeACLWithValue:(NSArray * _Nonnull)value params:(MTRWritePar } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.targets.count; ++i_3) { - if ( ! [element_0.targets[i_3] isKindOfClass: [MTRAccessControlClusterAccessControlTargetStruct class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.targets[i_3], MTRAccessControlClusterAccessControlTargetStruct); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.targets[i_3], NSStringFromClass(MTRAccessControlClusterAccessControlTargetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (MTRAccessControlClusterAccessControlTargetStruct *)element_0.targets[i_3]; if (element_3.cluster == nil) { listHolder_3->mList[i_3].cluster.SetNull(); } else { @@ -5870,11 +5875,12 @@ - (void)writeAttributeExtensionWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRAccessControlClusterAccessControlExtensionStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRAccessControlClusterAccessControlExtensionStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRAccessControlClusterAccessControlExtensionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRAccessControlClusterAccessControlExtensionStruct *)value[i_0]; listHolder_0->mList[i_0].data = AsByteSpan(element_0.data); listHolder_0->mList[i_0].fabricIndex = element_0.fabricIndex.unsignedCharValue; } @@ -10171,11 +10177,12 @@ - (void)writeAttributeDefaultOTAProvidersWithValue:(NSArray * _Nonnull)value par } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTROTASoftwareUpdateRequestorClusterProviderLocation class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTROTASoftwareUpdateRequestorClusterProviderLocation); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTROTASoftwareUpdateRequestorClusterProviderLocation.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTROTASoftwareUpdateRequestorClusterProviderLocation *)value[i_0]; listHolder_0->mList[i_0].providerNodeID = element_0.providerNodeID.unsignedLongLongValue; listHolder_0->mList[i_0].endpoint = element_0.endpoint.unsignedShortValue; listHolder_0->mList[i_0].fabricIndex = element_0.fabricIndex.unsignedCharValue; @@ -32215,11 +32222,12 @@ - (void)writeAttributeGroupKeyMapWithValue:(NSArray * _Nonnull)value params:(MTR } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRGroupKeyManagementClusterGroupKeyMapStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRGroupKeyManagementClusterGroupKeyMapStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRGroupKeyManagementClusterGroupKeyMapStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRGroupKeyManagementClusterGroupKeyMapStruct *)value[i_0]; listHolder_0->mList[i_0].groupId = element_0.groupId.unsignedShortValue; listHolder_0->mList[i_0].groupKeySetID = element_0.groupKeySetID.unsignedShortValue; listHolder_0->mList[i_0].fabricIndex = element_0.fabricIndex.unsignedCharValue; @@ -33396,11 +33404,12 @@ - (void)writeAttributeLabelListWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUserLabelClusterLabelStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUserLabelClusterLabelStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUserLabelClusterLabelStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUserLabelClusterLabelStruct *)value[i_0]; listHolder_0->mList[i_0].label = AsCharSpan(element_0.label); listHolder_0->mList[i_0].value = AsCharSpan(element_0.value); } @@ -64721,11 +64730,12 @@ - (void)writeAttributePresetsWithValue:(NSArray * _Nonnull)value params:(MTRWrit } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRThermostatClusterPresetStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRThermostatClusterPresetStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRThermostatClusterPresetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRThermostatClusterPresetStruct *)value[i_0]; if (element_0.presetHandle == nil) { listHolder_0->mList[i_0].presetHandle.SetNull(); } else { @@ -64835,11 +64845,12 @@ - (void)writeAttributeSchedulesWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRThermostatClusterScheduleStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRThermostatClusterScheduleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRThermostatClusterScheduleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRThermostatClusterScheduleStruct *)value[i_0]; if (element_0.scheduleHandle == nil) { listHolder_0->mList[i_0].scheduleHandle.SetNull(); } else { @@ -64865,11 +64876,12 @@ - (void)writeAttributeSchedulesWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.transitions.count; ++i_2) { - if ( ! [element_0.transitions[i_2] isKindOfClass: [MTRThermostatClusterScheduleTransitionStruct class]] ) { + auto element_2 = MTR_SAFE_CAST(element_0.transitions[i_2], MTRThermostatClusterScheduleTransitionStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.transitions[i_2], NSStringFromClass(MTRThermostatClusterScheduleTransitionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRThermostatClusterScheduleTransitionStruct *)element_0.transitions[i_2]; listHolder_2->mList[i_2].dayOfWeek = static_castmList[i_2].dayOfWeek)>>(element_2.dayOfWeek.unsignedCharValue); listHolder_2->mList[i_2].transitionTime = element_2.transitionTime.unsignedShortValue; if (element_2.presetHandle != nil) { @@ -97820,11 +97832,12 @@ - (void)writeAttributeTriggersWithValue:(NSArray * _Nonnull)value params:(MTRWri } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRZoneManagementClusterZoneTriggerControlStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRZoneManagementClusterZoneTriggerControlStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRZoneManagementClusterZoneTriggerControlStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRZoneManagementClusterZoneTriggerControlStruct *)value[i_0]; listHolder_0->mList[i_0].initialDuration = element_0.initialDuration.unsignedShortValue; listHolder_0->mList[i_0].augmentationDuration = element_0.augmentationDuration.unsignedShortValue; listHolder_0->mList[i_0].maxDuration = element_0.maxDuration.unsignedIntValue; @@ -104448,11 +104461,12 @@ - (void)writeAttributeListInt8uWithValue:(NSArray * _Nonnull)value params:(MTRWr } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSNumber class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *)value[i_0]; listHolder_0->mList[i_0] = element_0.unsignedCharValue; } cppValue = ListType_0(listHolder_0->mList, value.count); @@ -104533,11 +104547,12 @@ - (void)writeAttributeListOctetStringWithValue:(NSArray * _Nonnull)value params: } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSData class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], NSData); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSData *)value[i_0]; listHolder_0->mList[i_0] = AsByteSpan(element_0); } cppValue = ListType_0(listHolder_0->mList, value.count); @@ -104618,11 +104633,12 @@ - (void)writeAttributeListStructOctetStringWithValue:(NSArray * _Nonnull)value p } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUnitTestingClusterTestListStructOctet class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUnitTestingClusterTestListStructOctet); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUnitTestingClusterTestListStructOctet.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterTestListStructOctet *)value[i_0]; listHolder_0->mList[i_0].member1 = element_0.member1.unsignedLongLongValue; listHolder_0->mList[i_0].member2 = AsByteSpan(element_0.member2); } @@ -105088,11 +105104,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUnitTestingClusterNullablesAndOptionalsStruct class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUnitTestingClusterNullablesAndOptionalsStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUnitTestingClusterNullablesAndOptionalsStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterNullablesAndOptionalsStruct *)value[i_0]; if (element_0.nullableInt == nil) { listHolder_0->mList[i_0].nullableInt.SetNull(); } else { @@ -105197,11 +105214,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.nullableList.count; ++i_3) { - if ( ! [element_0.nullableList[i_3] isKindOfClass: [NSNumber class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.nullableList[i_3], NSNumber); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.nullableList[i_3], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSNumber *)element_0.nullableList[i_3]; listHolder_3->mList[i_3] = static_castmList[i_3])>>(element_3.unsignedCharValue); } nonNullValue_2 = ListType_3(listHolder_3->mList, element_0.nullableList.count); @@ -105222,11 +105240,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_0.optionalList.count; ++i_3) { - if ( ! [element_0.optionalList[i_3] isKindOfClass: [NSNumber class]] ) { + auto element_3 = MTR_SAFE_CAST(element_0.optionalList[i_3], NSNumber); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.optionalList[i_3], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSNumber *)element_0.optionalList[i_3]; listHolder_3->mList[i_3] = static_castmList[i_3])>>(element_3.unsignedCharValue); } definedValue_2 = ListType_3(listHolder_3->mList, element_0.optionalList.count); @@ -105251,11 +105270,12 @@ - (void)writeAttributeListNullablesAndOptionalsStructWithValue:(NSArray * _Nonnu } listFreer.add(listHolder_4); for (size_t i_4 = 0; i_4 < element_0.nullableOptionalList.count; ++i_4) { - if ( ! [element_0.nullableOptionalList[i_4] isKindOfClass: [NSNumber class]] ) { + auto element_4 = MTR_SAFE_CAST(element_0.nullableOptionalList[i_4], NSNumber); + if (!element_4) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.nullableOptionalList[i_4], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_4 = (NSNumber *)element_0.nullableOptionalList[i_4]; listHolder_4->mList[i_4] = static_castmList[i_4])>>(element_4.unsignedCharValue); } nonNullValue_3 = ListType_4(listHolder_4->mList, element_0.nullableOptionalList.count); @@ -105739,11 +105759,12 @@ - (void)writeAttributeListLongOctetStringWithValue:(NSArray * _Nonnull)value par } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [NSData class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], NSData); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSData *)value[i_0]; listHolder_0->mList[i_0] = AsByteSpan(element_0); } cppValue = ListType_0(listHolder_0->mList, value.count); @@ -105824,11 +105845,12 @@ - (void)writeAttributeListFabricScopedWithValue:(NSArray * _Nonnull)value params } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < value.count; ++i_0) { - if ( ! [value[i_0] isKindOfClass: [MTRUnitTestingClusterTestFabricScoped class]] ) { + auto element_0 = MTR_SAFE_CAST(value[i_0], MTRUnitTestingClusterTestFabricScoped); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", value[i_0], NSStringFromClass(MTRUnitTestingClusterTestFabricScoped.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterTestFabricScoped *)value[i_0]; listHolder_0->mList[i_0].fabricSensitiveInt8u = element_0.fabricSensitiveInt8u.unsignedCharValue; if (element_0.optionalFabricSensitiveInt8u != nil) { auto & definedValue_2 = listHolder_0->mList[i_0].optionalFabricSensitiveInt8u.Emplace(); @@ -105872,11 +105894,12 @@ - (void)writeAttributeListFabricScopedWithValue:(NSArray * _Nonnull)value params } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.fabricSensitiveInt8uList.count; ++i_2) { - if ( ! [element_0.fabricSensitiveInt8uList[i_2] isKindOfClass: [NSNumber class]] ) { + auto element_2 = MTR_SAFE_CAST(element_0.fabricSensitiveInt8uList[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.fabricSensitiveInt8uList[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *)element_0.fabricSensitiveInt8uList[i_2]; listHolder_2->mList[i_2] = element_2.unsignedCharValue; } listHolder_0->mList[i_0].fabricSensitiveInt8uList = ListType_2(listHolder_2->mList, element_0.fabricSensitiveInt8uList.count); diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index 6d8ddd6091..318455a23b 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -20,6 +20,7 @@ #import "MTRBaseDevice_Internal.h" #import "MTRCommandPayloadExtensions_Internal.h" #import "MTRCommandPayloads_Internal.h" +#import "MTRDefines_Internal.h" #import "MTRError_Internal.h" #import "MTRLogging_Internal.h" #import "NSDataSpanConversion.h" @@ -641,11 +642,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.groupList.count; ++i_0) { - if (![self.groupList[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.groupList[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.groupList[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.groupList[i_0]; listHolder_0->mList[i_0] = element_0.unsignedShortValue; } encodableStruct.groupList = ListType_0(listHolder_0->mList, self.groupList.count); @@ -2559,11 +2561,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arl.count; ++i_0) { - if (![self.arl[i_0] isKindOfClass:[MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.arl[i_0], MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arl[i_0], NSStringFromClass(MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRAccessControlClusterCommissioningAccessRestrictionEntryStruct *) self.arl[i_0]; listHolder_0->mList[i_0].endpoint = element_0.endpoint.unsignedShortValue; listHolder_0->mList[i_0].cluster = element_0.cluster.unsignedIntValue; { @@ -2576,11 +2579,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.restrictions.count; ++i_2) { - if (![element_0.restrictions[i_2] isKindOfClass:[MTRAccessControlClusterAccessRestrictionStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.restrictions[i_2], MTRAccessControlClusterAccessRestrictionStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.restrictions[i_2], NSStringFromClass(MTRAccessControlClusterAccessRestrictionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRAccessControlClusterAccessRestrictionStruct *) element_0.restrictions[i_2]; listHolder_2->mList[i_2].type = static_castmList[i_2].type)>>(element_2.type.unsignedCharValue); if (element_2.id == nil) { listHolder_2->mList[i_2].id.SetNull(); @@ -3910,11 +3914,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.protocolsSupported.count; ++i_0) { - if (![self.protocolsSupported[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.protocolsSupported[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.protocolsSupported[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.protocolsSupported[i_0]; listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); } encodableStruct.protocolsSupported = ListType_0(listHolder_0->mList, self.protocolsSupported.count); @@ -7601,11 +7606,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.timeZone.count; ++i_0) { - if (![self.timeZone[i_0] isKindOfClass:[MTRTimeSynchronizationClusterTimeZoneStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.timeZone[i_0], MTRTimeSynchronizationClusterTimeZoneStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.timeZone[i_0], NSStringFromClass(MTRTimeSynchronizationClusterTimeZoneStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRTimeSynchronizationClusterTimeZoneStruct *) self.timeZone[i_0]; listHolder_0->mList[i_0].offset = element_0.offset.intValue; listHolder_0->mList[i_0].validAt = element_0.validAt.unsignedLongLongValue; if (element_0.name != nil) { @@ -7785,11 +7791,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.dstOffset.count; ++i_0) { - if (![self.dstOffset[i_0] isKindOfClass:[MTRTimeSynchronizationClusterDSTOffsetStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.dstOffset[i_0], MTRTimeSynchronizationClusterDSTOffsetStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.dstOffset[i_0], NSStringFromClass(MTRTimeSynchronizationClusterDSTOffsetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRTimeSynchronizationClusterDSTOffsetStruct *) self.dstOffset[i_0]; listHolder_0->mList[i_0].offset = element_0.offset.intValue; listHolder_0->mList[i_0].validStarting = element_0.validStarting.unsignedLongLongValue; if (element_0.validUntil == nil) { @@ -13509,11 +13516,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.extensionFieldSets.count; ++i_0) { - if (![self.extensionFieldSets[i_0] isKindOfClass:[MTRScenesManagementClusterExtensionFieldSet class]]) { + auto element_0 = MTR_SAFE_CAST(self.extensionFieldSets[i_0], MTRScenesManagementClusterExtensionFieldSet); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.extensionFieldSets[i_0], NSStringFromClass(MTRScenesManagementClusterExtensionFieldSet.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRScenesManagementClusterExtensionFieldSet *) self.extensionFieldSets[i_0]; listHolder_0->mList[i_0].clusterID = element_0.clusterID.unsignedIntValue; { using ListType_2 = std::remove_reference_tmList[i_0].attributeValueList)>; @@ -13525,11 +13533,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.attributeValueList.count; ++i_2) { - if (![element_0.attributeValueList[i_2] isKindOfClass:[MTRScenesManagementClusterAttributeValuePairStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.attributeValueList[i_2], MTRScenesManagementClusterAttributeValuePairStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.attributeValueList[i_2], NSStringFromClass(MTRScenesManagementClusterAttributeValuePairStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRScenesManagementClusterAttributeValuePairStruct *) element_0.attributeValueList[i_2]; listHolder_2->mList[i_2].attributeID = element_2.attributeID.unsignedIntValue; if (element_2.valueUnsigned8 != nil) { auto & definedValue_4 = listHolder_2->mList[i_2].valueUnsigned8.Emplace(); @@ -15884,11 +15893,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.event.transitions.count; ++i_1) { - if (![self.event.transitions[i_1] isKindOfClass:[MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.event.transitions[i_1], MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.event.transitions[i_1], NSStringFromClass(MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRDemandResponseLoadControlClusterLoadControlEventTransitionStruct *) self.event.transitions[i_1]; listHolder_1->mList[i_1].duration = element_1.duration.unsignedShortValue; listHolder_1->mList[i_1].control = static_castmList[i_1].control)>>(element_1.control.unsignedShortValue); if (element_1.temperatureControl != nil) { @@ -16246,11 +16256,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.responses.count; ++i_1) { - if (![self.responses[i_1] isKindOfClass:[MTRMessagesClusterMessageResponseOptionStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.responses[i_1], MTRMessagesClusterMessageResponseOptionStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.responses[i_1], NSStringFromClass(MTRMessagesClusterMessageResponseOptionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRMessagesClusterMessageResponseOptionStruct *) self.responses[i_1]; if (element_1.messageResponseID != nil) { auto & definedValue_3 = listHolder_1->mList[i_1].messageResponseID.Emplace(); definedValue_3 = element_1.messageResponseID.unsignedIntValue; @@ -16354,11 +16365,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.messageIDs.count; ++i_0) { - if (![self.messageIDs[i_0] isKindOfClass:[NSData class]]) { + auto element_0 = MTR_SAFE_CAST(self.messageIDs[i_0], NSData); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.messageIDs[i_0], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSData *) self.messageIDs[i_0]; listHolder_0->mList[i_0] = AsByteSpan(element_0); } encodableStruct.messageIDs = ListType_0(listHolder_0->mList, self.messageIDs.count); @@ -16870,11 +16882,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.slotAdjustments.count; ++i_0) { - if (![self.slotAdjustments[i_0] isKindOfClass:[MTRDeviceEnergyManagementClusterSlotAdjustmentStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.slotAdjustments[i_0], MTRDeviceEnergyManagementClusterSlotAdjustmentStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.slotAdjustments[i_0], NSStringFromClass(MTRDeviceEnergyManagementClusterSlotAdjustmentStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRDeviceEnergyManagementClusterSlotAdjustmentStruct *) self.slotAdjustments[i_0]; listHolder_0->mList[i_0].slotIndex = element_0.slotIndex.unsignedCharValue; if (element_0.nominalPower != nil) { auto & definedValue_2 = listHolder_0->mList[i_0].nominalPower.Emplace(); @@ -16981,11 +16994,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.constraints.count; ++i_0) { - if (![self.constraints[i_0] isKindOfClass:[MTRDeviceEnergyManagementClusterConstraintsStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.constraints[i_0], MTRDeviceEnergyManagementClusterConstraintsStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.constraints[i_0], NSStringFromClass(MTRDeviceEnergyManagementClusterConstraintsStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRDeviceEnergyManagementClusterConstraintsStruct *) self.constraints[i_0]; listHolder_0->mList[i_0].startTime = element_0.startTime.unsignedIntValue; listHolder_0->mList[i_0].duration = element_0.duration.unsignedIntValue; if (element_0.nominalPower != nil) { @@ -17622,11 +17636,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.chargingTargetSchedules.count; ++i_0) { - if (![self.chargingTargetSchedules[i_0] isKindOfClass:[MTREnergyEVSEClusterChargingTargetScheduleStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.chargingTargetSchedules[i_0], MTREnergyEVSEClusterChargingTargetScheduleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.chargingTargetSchedules[i_0], NSStringFromClass(MTREnergyEVSEClusterChargingTargetScheduleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTREnergyEVSEClusterChargingTargetScheduleStruct *) self.chargingTargetSchedules[i_0]; listHolder_0->mList[i_0].dayOfWeekForSequence = static_castmList[i_0].dayOfWeekForSequence)>>(element_0.dayOfWeekForSequence.unsignedCharValue); { using ListType_2 = std::remove_reference_tmList[i_0].chargingTargets)>; @@ -17638,11 +17653,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.chargingTargets.count; ++i_2) { - if (![element_0.chargingTargets[i_2] isKindOfClass:[MTREnergyEVSEClusterChargingTargetStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.chargingTargets[i_2], MTREnergyEVSEClusterChargingTargetStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.chargingTargets[i_2], NSStringFromClass(MTREnergyEVSEClusterChargingTargetStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTREnergyEVSEClusterChargingTargetStruct *) element_0.chargingTargets[i_2]; listHolder_2->mList[i_2].targetTimeMinutesPastMidnight = element_2.targetTimeMinutesPastMidnight.unsignedShortValue; if (element_2.targetSoC != nil) { auto & definedValue_4 = listHolder_2->mList[i_2].targetSoC.Emplace(); @@ -21675,11 +21691,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.newAreas.count; ++i_0) { - if (![self.newAreas[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.newAreas[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.newAreas[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.newAreas[i_0]; listHolder_0->mList[i_0] = element_0.unsignedIntValue; } encodableStruct.newAreas = ListType_0(listHolder_0->mList, self.newAreas.count); @@ -22259,11 +22276,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.transitions.count; ++i_0) { - if (![self.transitions[i_0] isKindOfClass:[MTRThermostatClusterWeeklyScheduleTransitionStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.transitions[i_0], MTRThermostatClusterWeeklyScheduleTransitionStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.transitions[i_0], NSStringFromClass(MTRThermostatClusterWeeklyScheduleTransitionStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRThermostatClusterWeeklyScheduleTransitionStruct *) self.transitions[i_0]; listHolder_0->mList[i_0].transitionTime = element_0.transitionTime.unsignedShortValue; if (element_0.heatSetpoint == nil) { listHolder_0->mList[i_0].heatSetpoint.SetNull(); @@ -22812,11 +22830,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.attributeRequests.count; ++i_0) { - if (![self.attributeRequests[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.attributeRequests[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.attributeRequests[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.attributeRequests[i_0]; listHolder_0->mList[i_0] = element_0.unsignedIntValue; } encodableStruct.attributeRequests = ListType_0(listHolder_0->mList, self.attributeRequests.count); @@ -26190,11 +26209,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.channelList.count; ++i_1) { - if (![self.channelList[i_1] isKindOfClass:[MTRChannelClusterChannelInfoStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.channelList[i_1], MTRChannelClusterChannelInfoStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.channelList[i_1], NSStringFromClass(MTRChannelClusterChannelInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRChannelClusterChannelInfoStruct *) self.channelList[i_1]; listHolder_1->mList[i_1].majorNumber = element_1.majorNumber.unsignedShortValue; listHolder_1->mList[i_1].minorNumber = element_1.minorNumber.unsignedShortValue; if (element_1.name != nil) { @@ -26261,11 +26281,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.externalIDList.count; ++i_1) { - if (![self.externalIDList[i_1] isKindOfClass:[MTRChannelClusterAdditionalInfoStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.externalIDList[i_1], MTRChannelClusterAdditionalInfoStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.externalIDList[i_1], NSStringFromClass(MTRChannelClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRChannelClusterAdditionalInfoStruct *) self.externalIDList[i_1]; listHolder_1->mList[i_1].name = AsCharSpan(element_1.name); listHolder_1->mList[i_1].value = AsCharSpan(element_1.value); } @@ -26827,11 +26848,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.externalIDList.count; ++i_0) { - if (![self.externalIDList[i_0] isKindOfClass:[MTRChannelClusterAdditionalInfoStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.externalIDList[i_0], MTRChannelClusterAdditionalInfoStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.externalIDList[i_0], NSStringFromClass(MTRChannelClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRChannelClusterAdditionalInfoStruct *) self.externalIDList[i_0]; listHolder_0->mList[i_0].name = AsCharSpan(element_0.name); listHolder_0->mList[i_0].value = AsCharSpan(element_0.value); } @@ -26946,11 +26968,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.externalIDList.count; ++i_0) { - if (![self.externalIDList[i_0] isKindOfClass:[MTRChannelClusterAdditionalInfoStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.externalIDList[i_0], MTRChannelClusterAdditionalInfoStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.externalIDList[i_0], NSStringFromClass(MTRChannelClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRChannelClusterAdditionalInfoStruct *) self.externalIDList[i_0]; listHolder_0->mList[i_0].name = AsCharSpan(element_0.name); listHolder_0->mList[i_0].value = AsCharSpan(element_0.value); } @@ -28964,11 +28987,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.search.parameterList.count; ++i_1) { - if (![self.search.parameterList[i_1] isKindOfClass:[MTRContentLauncherClusterParameterStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.search.parameterList[i_1], MTRContentLauncherClusterParameterStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.search.parameterList[i_1], NSStringFromClass(MTRContentLauncherClusterParameterStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRContentLauncherClusterParameterStruct *) self.search.parameterList[i_1]; listHolder_1->mList[i_1].type = static_castmList[i_1].type)>>(element_1.type.unsignedCharValue); listHolder_1->mList[i_1].value = AsCharSpan(element_1.value); if (element_1.externalIDList != nil) { @@ -28983,11 +29007,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_4); for (size_t i_4 = 0; i_4 < element_1.externalIDList.count; ++i_4) { - if (![element_1.externalIDList[i_4] isKindOfClass:[MTRContentLauncherClusterAdditionalInfoStruct class]]) { + auto element_4 = MTR_SAFE_CAST(element_1.externalIDList[i_4], MTRContentLauncherClusterAdditionalInfoStruct); + if (!element_4) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.externalIDList[i_4], NSStringFromClass(MTRContentLauncherClusterAdditionalInfoStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_4 = (MTRContentLauncherClusterAdditionalInfoStruct *) element_1.externalIDList[i_4]; listHolder_4->mList[i_4].name = AsCharSpan(element_4.name); listHolder_4->mList[i_4].value = AsCharSpan(element_4.value); } @@ -29030,11 +29055,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_4); for (size_t i_4 = 0; i_4 < self.playbackPreferences.textTrack.characteristics.count; ++i_4) { - if (![self.playbackPreferences.textTrack.characteristics[i_4] isKindOfClass:[NSNumber class]]) { + auto element_4 = MTR_SAFE_CAST(self.playbackPreferences.textTrack.characteristics[i_4], NSNumber); + if (!element_4) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.playbackPreferences.textTrack.characteristics[i_4], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_4 = (NSNumber *) self.playbackPreferences.textTrack.characteristics[i_4]; listHolder_4->mList[i_4] = static_castmList[i_4])>>(element_4.unsignedCharValue); } definedValue_3 = ListType_4(listHolder_4->mList, self.playbackPreferences.textTrack.characteristics.count); @@ -29056,11 +29082,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < self.playbackPreferences.audioTracks.count; ++i_3) { - if (![self.playbackPreferences.audioTracks[i_3] isKindOfClass:[MTRContentLauncherClusterTrackPreferenceStruct class]]) { + auto element_3 = MTR_SAFE_CAST(self.playbackPreferences.audioTracks[i_3], MTRContentLauncherClusterTrackPreferenceStruct); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.playbackPreferences.audioTracks[i_3], NSStringFromClass(MTRContentLauncherClusterTrackPreferenceStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (MTRContentLauncherClusterTrackPreferenceStruct *) self.playbackPreferences.audioTracks[i_3]; listHolder_3->mList[i_3].languageCode = AsCharSpan(element_3.languageCode); if (element_3.characteristics != nil) { auto & definedValue_5 = listHolder_3->mList[i_3].characteristics.Emplace(); @@ -29074,11 +29101,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_6); for (size_t i_6 = 0; i_6 < element_3.characteristics.count; ++i_6) { - if (![element_3.characteristics[i_6] isKindOfClass:[NSNumber class]]) { + auto element_6 = MTR_SAFE_CAST(element_3.characteristics[i_6], NSNumber); + if (!element_6) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_3.characteristics[i_6], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_6 = (NSNumber *) element_3.characteristics[i_6]; listHolder_6->mList[i_6] = static_castmList[i_6])>>(element_6.unsignedCharValue); } definedValue_5 = ListType_6(listHolder_6->mList, element_3.characteristics.count); @@ -31387,11 +31415,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.zone.vertices.count; ++i_1) { - if (![self.zone.vertices[i_1] isKindOfClass:[MTRZoneManagementClusterTwoDCartesianVertexStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.zone.vertices[i_1], MTRZoneManagementClusterTwoDCartesianVertexStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.zone.vertices[i_1], NSStringFromClass(MTRZoneManagementClusterTwoDCartesianVertexStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRZoneManagementClusterTwoDCartesianVertexStruct *) self.zone.vertices[i_1]; listHolder_1->mList[i_1].x = element_1.x.unsignedShortValue; listHolder_1->mList[i_1].y = element_1.y.unsignedShortValue; } @@ -31579,11 +31608,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.zone.vertices.count; ++i_1) { - if (![self.zone.vertices[i_1] isKindOfClass:[MTRZoneManagementClusterTwoDCartesianVertexStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.zone.vertices[i_1], MTRZoneManagementClusterTwoDCartesianVertexStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.zone.vertices[i_1], NSStringFromClass(MTRZoneManagementClusterTwoDCartesianVertexStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRZoneManagementClusterTwoDCartesianVertexStruct *) self.zone.vertices[i_1]; listHolder_1->mList[i_1].x = element_1.x.unsignedShortValue; listHolder_1->mList[i_1].y = element_1.y.unsignedShortValue; } @@ -32929,11 +32959,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.streamPriorities.count; ++i_0) { - if (![self.streamPriorities[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.streamPriorities[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.streamPriorities[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.streamPriorities[i_0]; listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); } encodableStruct.streamPriorities = ListType_0(listHolder_0->mList, self.streamPriorities.count); @@ -33250,11 +33281,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.iceServers.count; ++i_1) { - if (![self.iceServers[i_1] isKindOfClass:[MTRWebRTCTransportProviderClusterICEServerStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.iceServers[i_1], MTRWebRTCTransportProviderClusterICEServerStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.iceServers[i_1], NSStringFromClass(MTRWebRTCTransportProviderClusterICEServerStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRWebRTCTransportProviderClusterICEServerStruct *) self.iceServers[i_1]; { using ListType_3 = std::remove_reference_tmList[i_1].urls)>; using ListMemberType_3 = ListMemberTypeGetter::Type; @@ -33265,11 +33297,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_1.urls.count; ++i_3) { - if (![element_1.urls[i_3] isKindOfClass:[NSString class]]) { + auto element_3 = MTR_SAFE_CAST(element_1.urls[i_3], NSString); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.urls[i_3], NSStringFromClass(NSString.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSString *) element_1.urls[i_3]; listHolder_3->mList[i_3] = AsCharSpan(element_3); } listHolder_1->mList[i_1].urls = ListType_3(listHolder_3->mList, element_1.urls.count); @@ -33568,11 +33601,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.iceServers.count; ++i_1) { - if (![self.iceServers[i_1] isKindOfClass:[MTRWebRTCTransportProviderClusterICEServerStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.iceServers[i_1], MTRWebRTCTransportProviderClusterICEServerStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.iceServers[i_1], NSStringFromClass(MTRWebRTCTransportProviderClusterICEServerStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRWebRTCTransportProviderClusterICEServerStruct *) self.iceServers[i_1]; { using ListType_3 = std::remove_reference_tmList[i_1].urls)>; using ListMemberType_3 = ListMemberTypeGetter::Type; @@ -33583,11 +33617,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_1.urls.count; ++i_3) { - if (![element_1.urls[i_3] isKindOfClass:[NSString class]]) { + auto element_3 = MTR_SAFE_CAST(element_1.urls[i_3], NSString); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.urls[i_3], NSStringFromClass(NSString.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSString *) element_1.urls[i_3]; listHolder_3->mList[i_3] = AsCharSpan(element_3); } listHolder_1->mList[i_1].urls = ListType_3(listHolder_3->mList, element_1.urls.count); @@ -34077,11 +34112,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.iceServers.count; ++i_1) { - if (![self.iceServers[i_1] isKindOfClass:[MTRWebRTCTransportRequestorClusterICEServerStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.iceServers[i_1], MTRWebRTCTransportRequestorClusterICEServerStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.iceServers[i_1], NSStringFromClass(MTRWebRTCTransportRequestorClusterICEServerStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRWebRTCTransportRequestorClusterICEServerStruct *) self.iceServers[i_1]; { using ListType_3 = std::remove_reference_tmList[i_1].urls)>; using ListMemberType_3 = ListMemberTypeGetter::Type; @@ -34092,11 +34128,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_3); for (size_t i_3 = 0; i_3 < element_1.urls.count; ++i_3) { - if (![element_1.urls[i_3] isKindOfClass:[NSString class]]) { + auto element_3 = MTR_SAFE_CAST(element_1.urls[i_3], NSString); + if (!element_3) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_1.urls[i_3], NSStringFromClass(NSString.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_3 = (NSString *) element_1.urls[i_3]; listHolder_3->mList[i_3] = AsCharSpan(element_3); } listHolder_1->mList[i_1].urls = ListType_3(listHolder_3->mList, element_1.urls.count); @@ -36079,11 +36116,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[MTRUnitTestingClusterNestedStructList class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], MTRUnitTestingClusterNestedStructList); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(MTRUnitTestingClusterNestedStructList.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterNestedStructList *) self.arg1[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c.a = element_0.c.a.unsignedCharValue; @@ -36108,11 +36146,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.d.count; ++i_2) { - if (![element_0.d[i_2] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.d[i_2], MTRUnitTestingClusterSimpleStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.d[i_2], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRUnitTestingClusterSimpleStruct *) element_0.d[i_2]; listHolder_2->mList[i_2].a = element_2.a.unsignedCharValue; listHolder_2->mList[i_2].b = element_2.b.boolValue; listHolder_2->mList[i_2].c = static_castmList[i_2].c)>>(element_2.c.unsignedCharValue); @@ -36141,11 +36180,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.e.count; ++i_2) { - if (![element_0.e[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.e[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.e[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.e[i_2]; listHolder_2->mList[i_2] = element_2.unsignedIntValue; } listHolder_0->mList[i_0].e = ListType_2(listHolder_2->mList, element_0.e.count); @@ -36163,11 +36203,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.f.count; ++i_2) { - if (![element_0.f[i_2] isKindOfClass:[NSData class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.f[i_2], NSData); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.f[i_2], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSData *) element_0.f[i_2]; listHolder_2->mList[i_2] = AsByteSpan(element_2); } listHolder_0->mList[i_0].f = ListType_2(listHolder_2->mList, element_0.f.count); @@ -36185,11 +36226,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.g.count; ++i_2) { - if (![element_0.g[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.g[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.g[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.g[i_2]; listHolder_2->mList[i_2] = element_2.unsignedCharValue; } listHolder_0->mList[i_0].g = ListType_2(listHolder_2->mList, element_0.g.count); @@ -36215,11 +36257,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg2.count; ++i_0) { - if (![self.arg2[i_0] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg2[i_0], MTRUnitTestingClusterSimpleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg2[i_0], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterSimpleStruct *) self.arg2[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c = static_castmList[i_0].c)>>(element_0.c.unsignedCharValue); @@ -36250,11 +36293,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg3.count; ++i_0) { - if (![self.arg3[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg3[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg3[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg3[i_0]; listHolder_0->mList[i_0] = static_castmList[i_0])>>(element_0.unsignedCharValue); } encodableStruct.arg3 = ListType_0(listHolder_0->mList, self.arg3.count); @@ -36274,11 +36318,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg4.count; ++i_0) { - if (![self.arg4[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg4[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg4[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg4[i_0]; listHolder_0->mList[i_0] = element_0.boolValue; } encodableStruct.arg4 = ListType_0(listHolder_0->mList, self.arg4.count); @@ -37257,11 +37302,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], MTRUnitTestingClusterSimpleStruct); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterSimpleStruct *) self.arg1[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c = static_castmList[i_0].c)>>(element_0.c.unsignedCharValue); @@ -37477,11 +37523,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg1[i_0]; listHolder_0->mList[i_0] = element_0.unsignedCharValue; } encodableStruct.arg1 = ListType_0(listHolder_0->mList, self.arg1.count); @@ -37683,11 +37730,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.d.count; ++i_1) { - if (![self.arg1.d[i_1] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.d[i_1], MTRUnitTestingClusterSimpleStruct); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.d[i_1], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (MTRUnitTestingClusterSimpleStruct *) self.arg1.d[i_1]; listHolder_1->mList[i_1].a = element_1.a.unsignedCharValue; listHolder_1->mList[i_1].b = element_1.b.boolValue; listHolder_1->mList[i_1].c = static_castmList[i_1].c)>>(element_1.c.unsignedCharValue); @@ -37716,11 +37764,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.e.count; ++i_1) { - if (![self.arg1.e[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.e[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.e[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.arg1.e[i_1]; listHolder_1->mList[i_1] = element_1.unsignedIntValue; } encodableStruct.arg1.e = ListType_1(listHolder_1->mList, self.arg1.e.count); @@ -37738,11 +37787,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.f.count; ++i_1) { - if (![self.arg1.f[i_1] isKindOfClass:[NSData class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.f[i_1], NSData); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.f[i_1], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSData *) self.arg1.f[i_1]; listHolder_1->mList[i_1] = AsByteSpan(element_1); } encodableStruct.arg1.f = ListType_1(listHolder_1->mList, self.arg1.f.count); @@ -37760,11 +37810,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.arg1.g.count; ++i_1) { - if (![self.arg1.g[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.arg1.g[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1.g[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.arg1.g[i_1]; listHolder_1->mList[i_1] = element_1.unsignedCharValue; } encodableStruct.arg1.g = ListType_1(listHolder_1->mList, self.arg1.g.count); @@ -37952,11 +38003,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[MTRUnitTestingClusterNestedStructList class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], MTRUnitTestingClusterNestedStructList); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(MTRUnitTestingClusterNestedStructList.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (MTRUnitTestingClusterNestedStructList *) self.arg1[i_0]; listHolder_0->mList[i_0].a = element_0.a.unsignedCharValue; listHolder_0->mList[i_0].b = element_0.b.boolValue; listHolder_0->mList[i_0].c.a = element_0.c.a.unsignedCharValue; @@ -37981,11 +38033,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.d.count; ++i_2) { - if (![element_0.d[i_2] isKindOfClass:[MTRUnitTestingClusterSimpleStruct class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.d[i_2], MTRUnitTestingClusterSimpleStruct); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.d[i_2], NSStringFromClass(MTRUnitTestingClusterSimpleStruct.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (MTRUnitTestingClusterSimpleStruct *) element_0.d[i_2]; listHolder_2->mList[i_2].a = element_2.a.unsignedCharValue; listHolder_2->mList[i_2].b = element_2.b.boolValue; listHolder_2->mList[i_2].c = static_castmList[i_2].c)>>(element_2.c.unsignedCharValue); @@ -38014,11 +38067,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.e.count; ++i_2) { - if (![element_0.e[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.e[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.e[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.e[i_2]; listHolder_2->mList[i_2] = element_2.unsignedIntValue; } listHolder_0->mList[i_0].e = ListType_2(listHolder_2->mList, element_0.e.count); @@ -38036,11 +38090,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.f.count; ++i_2) { - if (![element_0.f[i_2] isKindOfClass:[NSData class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.f[i_2], NSData); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.f[i_2], NSStringFromClass(NSData.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSData *) element_0.f[i_2]; listHolder_2->mList[i_2] = AsByteSpan(element_2); } listHolder_0->mList[i_0].f = ListType_2(listHolder_2->mList, element_0.f.count); @@ -38058,11 +38113,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < element_0.g.count; ++i_2) { - if (![element_0.g[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(element_0.g[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", element_0.g[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) element_0.g[i_2]; listHolder_2->mList[i_2] = element_2.unsignedCharValue; } listHolder_0->mList[i_0].g = ListType_2(listHolder_2->mList, element_0.g.count); @@ -38249,11 +38305,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_0); for (size_t i_0 = 0; i_0 < self.arg1.count; ++i_0) { - if (![self.arg1[i_0] isKindOfClass:[NSNumber class]]) { + auto element_0 = MTR_SAFE_CAST(self.arg1[i_0], NSNumber); + if (!element_0) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.arg1[i_0], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_0 = (NSNumber *) self.arg1[i_0]; listHolder_0->mList[i_0] = element_0.unsignedCharValue; } encodableStruct.arg1 = ListType_0(listHolder_0->mList, self.arg1.count); @@ -38868,11 +38925,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.nullableList.count; ++i_1) { - if (![self.nullableList[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.nullableList[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.nullableList[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.nullableList[i_1]; listHolder_1->mList[i_1] = static_castmList[i_1])>>(element_1.unsignedCharValue); } nonNullValue_0 = ListType_1(listHolder_1->mList, self.nullableList.count); @@ -38895,11 +38953,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_1); for (size_t i_1 = 0; i_1 < self.optionalList.count; ++i_1) { - if (![self.optionalList[i_1] isKindOfClass:[NSNumber class]]) { + auto element_1 = MTR_SAFE_CAST(self.optionalList[i_1], NSNumber); + if (!element_1) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.optionalList[i_1], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_1 = (NSNumber *) self.optionalList[i_1]; listHolder_1->mList[i_1] = static_castmList[i_1])>>(element_1.unsignedCharValue); } definedValue_0 = ListType_1(listHolder_1->mList, self.optionalList.count); @@ -38926,11 +38985,12 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } listFreer.add(listHolder_2); for (size_t i_2 = 0; i_2 < self.nullableOptionalList.count; ++i_2) { - if (![self.nullableOptionalList[i_2] isKindOfClass:[NSNumber class]]) { + auto element_2 = MTR_SAFE_CAST(self.nullableOptionalList[i_2], NSNumber); + if (!element_2) { // Wrong kind of value. + MTR_LOG_ERROR("%@ incorrectly present in list of %@", self.nullableOptionalList[i_2], NSStringFromClass(NSNumber.class)); return CHIP_ERROR_INVALID_ARGUMENT; } - auto element_2 = (NSNumber *) self.nullableOptionalList[i_2]; listHolder_2->mList[i_2] = static_castmList[i_2])>>(element_2.unsignedCharValue); } nonNullValue_1 = ListType_2(listHolder_2->mList, self.nullableOptionalList.count); From 057f7db08360cb9c13146ff959b8be0d010ea32f Mon Sep 17 00:00:00 2001 From: shgutte <102281713+shgutte@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:21:37 +0530 Subject: [PATCH 067/219] [Silabs] Adds changes for min and max values of refrigerator temperature controlled cabinet (#36592) * Adds changes for min and max values of refrigerator temperature control cabinet * Removed the manual set for temperatureset-point * Converting Fahrenheit to Celsius min max values --- .../silabs/data_model/refrigerator-thread-app.matter | 8 ++++---- .../silabs/data_model/refrigerator-thread-app.zap | 8 ++++---- .../silabs/data_model/refrigerator-wifi-app.matter | 8 ++++---- .../silabs/data_model/refrigerator-wifi-app.zap | 8 ++++---- .../refrigerator-app/silabs/src/RefrigeratorManager.cpp | 1 - 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter index 49f9672046..4cafac3925 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter @@ -1955,8 +1955,8 @@ endpoint 2 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = -18; + ram attribute maxTemperature default = -15; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; @@ -1985,8 +1985,8 @@ endpoint 3 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = 0; + ram attribute maxTemperature default = 4; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap index 3a6bcd8331..31351d35ef 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap @@ -3770,7 +3770,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-18", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3786,7 +3786,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-15", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4119,7 +4119,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4135,7 +4135,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter index b4386fe9ef..234974cf1d 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter @@ -1863,8 +1863,8 @@ endpoint 2 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = -18; + ram attribute maxTemperature default = -15; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; @@ -1893,8 +1893,8 @@ endpoint 3 { server cluster TemperatureControl { ram attribute temperatureSetpoint; - ram attribute minTemperature; - ram attribute maxTemperature; + ram attribute minTemperature default = 0; + ram attribute maxTemperature default = 4; ram attribute step; callback attribute generatedCommandList; callback attribute acceptedCommandList; diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap index addfd6f519..34ba99ff80 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap @@ -3675,7 +3675,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-18", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3691,7 +3691,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "-15", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4024,7 +4024,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4040,7 +4040,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp b/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp index 09ab827e9d..3edb405a76 100644 --- a/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp +++ b/examples/refrigerator-app/silabs/src/RefrigeratorManager.cpp @@ -102,7 +102,6 @@ void RefrigeratorManager::TempCtrlAttributeChangeHandler(EndpointId endpointId, case TempCtrlAttr::TemperatureSetpoint::Id: { int16_t temperatureSetpoint = ConvertToPrintableTemp(static_cast(*value)); mTemperatureSetpoint = temperatureSetpoint; - TempCtrlAttr::TemperatureSetpoint::Set(endpointId, temperatureSetpoint); } break; default: { From 737c8f29043cfb3d99aafa6da509aa753967ace9 Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Fri, 22 Nov 2024 04:53:00 +0100 Subject: [PATCH 068/219] [Darwin][Ble] Keep scanning while connecting to a device until didConnectPeripheral fires (#36595) --- src/platform/Darwin/BleConnectionDelegateImpl.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/Darwin/BleConnectionDelegateImpl.mm b/src/platform/Darwin/BleConnectionDelegateImpl.mm index b0c1e2ef70..7b5d68bab1 100644 --- a/src/platform/Darwin/BleConnectionDelegateImpl.mm +++ b/src/platform/Darwin/BleConnectionDelegateImpl.mm @@ -447,6 +447,7 @@ - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPerip MATTER_LOG_METRIC_BEGIN(kMetricBLEDiscoveredServices); [peripheral setDelegate:self]; [peripheral discoverServices:nil]; + [self stopScanning]; } // End CBCentralManagerDelegate @@ -734,7 +735,7 @@ - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscrimi MATTER_LOG_METRIC_BEGIN(kMetricBLEDiscoveredMatchingPeripheral); ChipLogProgress(Ble, "Connecting to cached device: %p", peripheral); [self connect:peripheral]; - [self stopScanning]; + // The cached peripheral might be obsolete, so continue scanning until didConnectPeripheral is triggered. } else { [self setupTimer:kScanningWithDiscriminatorTimeoutInSeconds]; } From 04e6a68cf8aa2c2d24dd1decb74d71a6f7a70dfe Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 21 Nov 2024 23:02:38 -0500 Subject: [PATCH 069/219] Use _deviceForNodeID:createIfNeeded: in more places. (#36602) We had some manual lock-and-get code that can go away now. --- .../Framework/CHIP/MTRDeviceController_Concrete.mm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm index 4dfffcbb89..99398867cc 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm @@ -1619,12 +1619,9 @@ - (void)invalidateCASESessionForNode:(NSNumber *)nodeID; - (void)operationalInstanceAdded:(NSNumber *)nodeID { - // Don't use deviceForNodeID here, because we don't want to create the - // device if it does not already exist. - os_unfair_lock_lock(self.deviceMapLock); - MTRDevice * device = [self.nodeIDToDeviceMap objectForKey:nodeID]; - os_unfair_lock_unlock(self.deviceMapLock); - + // If we don't have an existing MTRDevice for this node ID, that's fine; + // nothing to do. + MTRDevice * device = [self _deviceForNodeID:nodeID createIfNeeded:NO]; if (device == nil) { return; } From d27a0990d998524ae7e62bb1df5e2e1a943c8e5a Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Fri, 22 Nov 2024 21:16:23 +0530 Subject: [PATCH 070/219] ESP32: Fix building chip_gn for cmake v3.31.x and onwards (#36606) remove the WORKING_DIRECTORY from chip_gn target For cmake v3.31.x, custom command generated for chip_gn-build in build.ninja concats the $WORKING_DIRECTORY and $BUILD_DIR paths and it mess up the chip_gn step when building example. COMMAND = cd "/Users/account/esp-matter/connectedhomeip/connectedhomeip/config/esp32/components/chip;/Users/account/esp-matter/examples/light/build/esp-idf/chip" && ninja esp32 For cmake version prior to v3.31, it do not prepend the $WORKING_DIRECTORY path. COMMAND = cd /Users/account/esp-matter/examples/light/build/esp-idf/chip && ninja esp32 This could be becuase of https://github.com/Kitware/CMake/commit/f5f80305ef69dd33fbedd31ef1d2cfd3d2bc15b4 related issue - https://github.com/espressif/esp-matter/issues/1157 --- config/esp32/components/chip/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 40f5c0cea2..d3106bad55 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -389,7 +389,6 @@ externalproject_add( BUILD_COMMAND ninja "esp32" INSTALL_COMMAND "" BUILD_BYPRODUCTS ${chip_libraries} - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} DEPENDS args_gn BUILD_ALWAYS 1 ) From 0b819f43d67115ca2b5fb2d8b18226a809969090 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Fri, 22 Nov 2024 16:46:59 +0100 Subject: [PATCH 071/219] Add SWVersion in OTAFragment (#36590) --- .../OtaProviderClientFragment.kt | 8 +++-- .../layout/ota_provider_client_fragment.xml | 29 ++++++++++++++++++- .../app/src/main/res/values/strings.xml | 2 ++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt index 13caa7b50e..779ab2550e 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/OtaProviderClientFragment.kt @@ -63,6 +63,9 @@ class OtaProviderClientFragment : Fragment() { private val vendorId: Int get() = binding.vendorIdEd.text.toString().toInt() + private val softwareVersion: Long + get() = binding.softwareVersionEd.text.toString().toLongOrNull() ?: 0L + private val otaProviderCallback = OtaProviderCallback() private val binding get() = _binding!! @@ -471,8 +474,8 @@ class OtaProviderClientFragment : Fragment() { } private fun updateOTAStatusBtnClick() { - val version = 2L - val versionString = "2.0" + val version = softwareVersion + val versionString = softwareVersion.toString() val filename = binding.firmwareFileTv.text.toString() Log.d(TAG, "updateOTAStatusBtnClick : $filename") @@ -648,6 +651,7 @@ class OtaProviderClientFragment : Fragment() { bufferedInputStream?.close() inputStream = null bufferedInputStream = null + showMessage("BDXTransfer End! - ErrorCode: $errorCode") } override fun handleBDXQuery( diff --git a/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml index 3d591f38b3..25ff9c252b 100644 --- a/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml +++ b/examples/android/CHIPTool/app/src/main/res/layout/ota_provider_client_fragment.xml @@ -153,11 +153,38 @@ android:padding="8dp" android:textSize="16sp" /> + + + + Read Write Vendor ID + SW Version + 1 Select Firmware Update OTA Status Start Firmware Update From 3b16d7138fec2f85ae8520a572baacabc134324a Mon Sep 17 00:00:00 2001 From: Marian CHEREJI <122872376+marian-chereji-nxp@users.noreply.github.com> Date: Fri, 22 Nov 2024 17:47:26 +0200 Subject: [PATCH 072/219] [nxp][platform][mcxw71_k32w1] Relocate key storage default option to example apps args definition files (#36577) The GN args file for the MCXW71/K32W1 platforms defines a default for the "nxp_nvm_component" option which prevents the users from selecting a different option in the command line. The default value for this build option is already defined by the third_party/nxp/nxp_matter_support/gn_build/nxp_sdk.gni GN arguments file. If one would want to override the default, this has to be done in the scope of the application so that the user can also override the build option from the command line. Signed-off-by: Marian Chereji --- examples/contact-sensor-app/nxp/k32w1/args.gni | 2 ++ examples/contact-sensor-app/nxp/mcxw71/args.gni | 2 ++ examples/lighting-app/nxp/k32w1/args.gni | 2 ++ examples/lighting-app/nxp/mcxw71/args.gni | 2 ++ src/platform/nxp/mcxw71_k32w1/args.gni | 1 - 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/contact-sensor-app/nxp/k32w1/args.gni b/examples/contact-sensor-app/nxp/k32w1/args.gni index 363718f1a8..ee29002e00 100644 --- a/examples/contact-sensor-app/nxp/k32w1/args.gni +++ b/examples/contact-sensor-app/nxp/k32w1/args.gni @@ -42,3 +42,5 @@ chip_openthread_ftd = false nxp_enable_ot_cli = false chip_with_diag_logs_demo = true + +nxp_nvm_component = "nvs" diff --git a/examples/contact-sensor-app/nxp/mcxw71/args.gni b/examples/contact-sensor-app/nxp/mcxw71/args.gni index bf06f4e494..87a3b49632 100644 --- a/examples/contact-sensor-app/nxp/mcxw71/args.gni +++ b/examples/contact-sensor-app/nxp/mcxw71/args.gni @@ -40,3 +40,5 @@ chip_openthread_ftd = false nxp_enable_ot_cli = false chip_with_diag_logs_demo = true + +nxp_nvm_component = "nvs" diff --git a/examples/lighting-app/nxp/k32w1/args.gni b/examples/lighting-app/nxp/k32w1/args.gni index 3d026f1fb4..078847b982 100644 --- a/examples/lighting-app/nxp/k32w1/args.gni +++ b/examples/lighting-app/nxp/k32w1/args.gni @@ -35,5 +35,7 @@ chip_system_config_provide_statistics = false chip_system_config_use_open_thread_inet_endpoints = true chip_with_lwip = false +nxp_nvm_component = "nvs" + nxp_use_smu2_static = true nxp_use_smu2_dynamic = true diff --git a/examples/lighting-app/nxp/mcxw71/args.gni b/examples/lighting-app/nxp/mcxw71/args.gni index 6be0421109..5e8897a0d7 100644 --- a/examples/lighting-app/nxp/mcxw71/args.gni +++ b/examples/lighting-app/nxp/mcxw71/args.gni @@ -35,5 +35,7 @@ chip_system_config_provide_statistics = false chip_system_config_use_open_thread_inet_endpoints = true chip_with_lwip = false +nxp_nvm_component = "nvs" + nxp_use_smu2_static = true nxp_use_smu2_dynamic = true diff --git a/src/platform/nxp/mcxw71_k32w1/args.gni b/src/platform/nxp/mcxw71_k32w1/args.gni index 7ec8fdf3d5..50cfbaba96 100644 --- a/src/platform/nxp/mcxw71_k32w1/args.gni +++ b/src/platform/nxp/mcxw71_k32w1/args.gni @@ -21,7 +21,6 @@ openthread_root = nxp_platform = "mcxw71_k32w1" nxp_sdk_name = "mcxw71_k32w1_sdk" nxp_device_layer = "nxp/${nxp_platform}" -nxp_nvm_component = "nvs" nxp_use_lwip = false # ARM architecture flags will be set based on NXP board. From 7cb6510466acdc5947792e57460bb953c85374df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Fri, 22 Nov 2024 16:54:22 +0100 Subject: [PATCH 073/219] energy-management-app: Add boost state in WaterHeater README (#36338) * Add boost state in WaterHeater README * Format --- examples/energy-management-app/linux/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md index 87b6d9dd93..637b80f95d 100644 --- a/examples/energy-management-app/linux/README.md +++ b/examples/energy-management-app/linux/README.md @@ -613,3 +613,19 @@ Step-by-step: [1730312762.703] [2153606:2153609] [TOO] TankVolume: 100 ``` + +1. Set boost state: + + - `durationIndicates` the time period in seconds for which the BOOST state + is activated before it automatically reverts to the previous mode (e.g. + OFF, MANUAL or TIMED). + + ``` + ./out/linux-x64-chip-tool-no-ble/chip-tool waterheatermanagement boost '{ "duration": 1800 }' 0x12344321 2 + ``` + +1. Cancel boost state: + + ``` + ./out/linux-x64-chip-tool-no-ble/chip-tool waterheatermanagement cancel-boost 0x12344321 2 + ``` From 1ba5de6e210b5683b1e2ac90d4251dcbd6fff7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Fri, 22 Nov 2024 16:54:48 +0100 Subject: [PATCH 074/219] Implement Operational State Cluster PhaseList attribute (#36350) * Update chef-operational-state-delegate-impl.h opPhase * Update chef-operational-state-delegate-impl.h Implement mOperationalPhaseList * Restyle * Update chef-operational-state-delegate-impl.h Use CharSpan * Update chef-operational-state-delegate-impl.h * Clean --- examples/chef/common/chef-operational-state-delegate-impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/chef/common/chef-operational-state-delegate-impl.h b/examples/chef/common/chef-operational-state-delegate-impl.h index 884a6f28c2..dcac2049d9 100644 --- a/examples/chef/common/chef-operational-state-delegate-impl.h +++ b/examples/chef/common/chef-operational-state-delegate-impl.h @@ -110,6 +110,7 @@ class OperationalStateDelegate : public GenericOperationalStateDelegateImpl GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)), GenericOperationalState(to_underlying(OperationalStateEnum::kError)), }; + const CharSpan opPhaseList[3] = { "pre-soak"_span, "rinse"_span, "spin"_span }; public: const uint32_t kExampleCountDown = 30; @@ -117,6 +118,7 @@ class OperationalStateDelegate : public GenericOperationalStateDelegateImpl OperationalStateDelegate() { GenericOperationalStateDelegateImpl::mOperationalStateList = Span(opStateList); + GenericOperationalStateDelegateImpl::mOperationalPhaseList = Span(opPhaseList); } /** From d1600cc846b862fe9cb64c3c33085ef04f5b4bd4 Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Fri, 22 Nov 2024 23:56:19 +0800 Subject: [PATCH 075/219] [ESP32]: fix compile error for c6 bt lib path (#36332) * esp32: fix compile error for c6 bt lib path * Add warning message if no libble_app.a is found. --- config/esp32/components/chip/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index d3106bad55..0047cfecc7 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -430,7 +430,13 @@ if(CONFIG_BT_ENABLED) if((target_name STREQUAL "esp32h2") OR (target_name STREQUAL "esp32c2") OR (target_name STREQUAL "esp32c6")) idf_component_get_property(bt_dir bt COMPONENT_DIR) list(APPEND chip_libraries $) - list(APPEND chip_libraries "${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a") + if (EXISTS ${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a) + list(APPEND chip_libraries "${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a") + elseif(EXISTS ${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/${target_name}/libble_app.a) + list(APPEND chip_libraries "${bt_dir}/controller/lib_${target_name}/${target_name}-bt-lib/${target_name}/libble_app.a") + else() + message(WARNING "There is no libble_app.a in the given path") + endif() elseif(target_name STREQUAL "esp32p4") list(APPEND chip_libraries $) else() From 403d595481cc4b7a11732fe3b4f59ce8a0cf1b00 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 22 Nov 2024 08:04:09 -0800 Subject: [PATCH 076/219] [Fabric-Sync] Cleanup pass through APIs (#36604) --- examples/fabric-sync/admin/DeviceManager.cpp | 75 ------------------- examples/fabric-sync/admin/DeviceManager.h | 65 ---------------- examples/fabric-sync/admin/FabricAdmin.cpp | 8 +- examples/fabric-sync/admin/PairingManager.cpp | 6 ++ .../bridge/include/FabricAdminDelegate.h | 13 ++++ .../fabric-sync/shell/AddBridgeCommand.cpp | 2 +- .../fabric-sync/shell/AddDeviceCommand.cpp | 2 +- .../fabric-sync/shell/RemoveBridgeCommand.cpp | 2 +- .../fabric-sync/shell/RemoveDeviceCommand.cpp | 2 +- .../fabric-sync/shell/SyncDeviceCommand.cpp | 7 +- 10 files changed, 36 insertions(+), 146 deletions(-) diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index 00e6988a2c..a632844195 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -212,81 +212,6 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin } } -CHIP_ERROR DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort) -{ - CHIP_ERROR err = PairingManager::Instance().PairDevice(nodeId, setupPINCode, deviceRemoteIp, deviceRemotePort); - - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, - "Failed to pair remote fabric bridge: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, - ChipLogValueX64(nodeId), err.Format()); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::PairRemoteDevice(NodeId nodeId, const char * payload) -{ - CHIP_ERROR err = PairingManager::Instance().PairDeviceWithCode(nodeId, payload); - - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, - ChipLogValueX64(nodeId), err.Format()); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::PairRemoteDevice(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort) -{ - CHIP_ERROR err = PairingManager::Instance().PairDevice(nodeId, setupPINCode, deviceRemoteIp, deviceRemotePort); - - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, - ChipLogValueX64(nodeId), err.Format()); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::UnpairRemoteFabricBridge() -{ - if (mRemoteBridgeNodeId == kUndefinedNodeId) - { - ChipLogError(NotSpecified, "Remote bridge node ID is undefined; cannot unpair device."); - return CHIP_ERROR_INCORRECT_STATE; - } - - CHIP_ERROR err = PairingManager::Instance().UnpairDevice(mRemoteBridgeNodeId); - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair remote bridge device " ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceManager::UnpairRemoteDevice(NodeId nodeId) -{ - CHIP_ERROR err = PairingManager::Instance().UnpairDevice(nodeId); - if (err != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair remote device " ChipLogFormatX64, ChipLogValueX64(nodeId)); - return err; - } - - return CHIP_NO_ERROR; -} - void DeviceManager::SubscribeRemoteFabricBridge() { ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); diff --git a/examples/fabric-sync/admin/DeviceManager.h b/examples/fabric-sync/admin/DeviceManager.h index d2f829ec40..a8a012ce9c 100644 --- a/examples/fabric-sync/admin/DeviceManager.h +++ b/examples/fabric-sync/admin/DeviceManager.h @@ -140,71 +140,6 @@ class DeviceManager */ void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); - /** - * @brief Pair a remote fabric bridge with a given node ID. - * - * This function initiates the pairing process for a remote fabric bridge using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param setupPINCode The setup PIN code used to authenticate the pairing process. - * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. - * @param deviceRemotePort The secured device port of the remote device that is being paired as part of the fabric bridge. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR PairRemoteFabricBridge(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort); - - /** - * @brief Pair a remote Matter device to the current fabric. - * - * This function initiates the pairing process for a remote device using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param payload The the QR code payload or a manual pairing code generated by the first commissioner - * instance when opened commissioning window. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR PairRemoteDevice(chip::NodeId nodeId, const char * payload); - - /** - * @brief Pair a remote Matter device to the current fabric. - * - * This function initiates the pairing process for a remote device using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param setupPINCode The setup PIN code used to authenticate the pairing process. - * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. - * @param deviceRemotePort The secured device port of the remote device that is being paired as part of the fabric bridge. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR PairRemoteDevice(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, uint16_t deviceRemotePort); - - /** - * @brief Unpair the remote Matter fabric bridge. - * - * This function initiates the unpairing process for the remote Matter fabric bridge from the current fabric. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR UnpairRemoteFabricBridge(); - - /** - * @brief Unpair a specific remote Matter device from the current fabric. - * - * This function removes a specific remote device, identified by the node ID, from the fabric. - * - * @param nodeId The user-defined ID of the node that is being unpaired. - * - * @return CHIP_ERROR Returns CHIP_NO_ERROR on success or an appropriate error code on failure. - */ - CHIP_ERROR UnpairRemoteDevice(chip::NodeId nodeId); - void SubscribeRemoteFabricBridge(); void ReadSupportedDeviceCategories(); diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index afc9456b2a..de498cdb31 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -115,7 +115,13 @@ FabricAdmin::CommissionRemoteBridge(Controller::CommissioningWindowPasscodeParam usleep(kCommissionPrepareTimeMs * 1000); PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str()); + err = PairingManager::Instance().PairDeviceWithCode(mNodeId, code.c_str()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, + "Failed to commission remote bridge device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mNodeId), err.Format()); + } } else { diff --git a/examples/fabric-sync/admin/PairingManager.cpp b/examples/fabric-sync/admin/PairingManager.cpp index 63a2c67c84..e7585ca6df 100644 --- a/examples/fabric-sync/admin/PairingManager.cpp +++ b/examples/fabric-sync/admin/PairingManager.cpp @@ -636,6 +636,12 @@ CHIP_ERROR PairingManager::PairDevice(chip::NodeId nodeId, uint32_t setupPINCode CHIP_ERROR PairingManager::UnpairDevice(NodeId nodeId) { + if (nodeId == kUndefinedNodeId) + { + ChipLogError(NotSpecified, "node ID is undefined; cannot unpair device."); + return CHIP_ERROR_INCORRECT_STATE; + } + return DeviceLayer::SystemLayer().ScheduleLambda([nodeId]() { PairingManager & self = PairingManager::Instance(); diff --git a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h index 1637c5294f..b37273aa7c 100644 --- a/examples/fabric-sync/bridge/include/FabricAdminDelegate.h +++ b/examples/fabric-sync/bridge/include/FabricAdminDelegate.h @@ -61,6 +61,19 @@ class FabricAdminDelegate virtual CHIP_ERROR CommissionRemoteBridge(chip::Controller::CommissioningWindowPasscodeParams params, chip::VendorId vendorId, uint16_t productId) = 0; + /** + * Sends a request to keep a device active for a specified duration. + * + * @param ScopedNodeId Identifies the target node within the fabric. + * @param StayActiveDurationMs The duration for which the device should stay active. + * @param TimeoutMs Timeout for the operation. + * + * @return CHIP_ERROR An error code indicating the success or failure of the + * operation. + * - CHIP_NO_ERROR: Request processed successfully. + * - CHIP_ERROR_INTERNAL: An internal error occurred during the preparation or sending + * of the command. + */ virtual CHIP_ERROR KeepActive(chip::ScopedNodeId scopedNodeId, uint32_t stayActiveDurationMs, uint32_t timeoutMs) = 0; }; diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index e06f8882d2..4ddebececd 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -88,7 +88,7 @@ CHIP_ERROR AddBridgeCommand::RunCommand() ChipLogProgress(NotSpecified, "Running AddBridgeCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); - return admin::DeviceManager::Instance().PairRemoteFabricBridge(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::PairingManager::Instance().PairDevice(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/AddDeviceCommand.cpp b/examples/fabric-sync/shell/AddDeviceCommand.cpp index a79e4696ca..f5098d2af7 100644 --- a/examples/fabric-sync/shell/AddDeviceCommand.cpp +++ b/examples/fabric-sync/shell/AddDeviceCommand.cpp @@ -76,7 +76,7 @@ CHIP_ERROR AddDeviceCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceManager::Instance().PairRemoteDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); + return admin::PairingManager::Instance().PairDevice(mNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp index 9a33b0b11b..4340a3d286 100644 --- a/examples/fabric-sync/shell/RemoveBridgeCommand.cpp +++ b/examples/fabric-sync/shell/RemoveBridgeCommand.cpp @@ -66,7 +66,7 @@ CHIP_ERROR RemoveBridgeCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - return admin::DeviceManager::Instance().UnpairRemoteFabricBridge(); + return admin::PairingManager::Instance().UnpairDevice(bridgeNodeId); } } // namespace commands diff --git a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp index 5e316658d5..649523c559 100644 --- a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp +++ b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp @@ -63,7 +63,7 @@ CHIP_ERROR RemoveDeviceCommand::RunCommand() ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: %lu", mNodeId); - return admin::DeviceManager::Instance().UnpairRemoteDevice(mNodeId); + return admin::PairingManager::Instance().UnpairDevice(mNodeId); } } // namespace commands diff --git a/examples/fabric-sync/shell/SyncDeviceCommand.cpp b/examples/fabric-sync/shell/SyncDeviceCommand.cpp index 871c8d68fe..81c822dfa6 100644 --- a/examples/fabric-sync/shell/SyncDeviceCommand.cpp +++ b/examples/fabric-sync/shell/SyncDeviceCommand.cpp @@ -53,7 +53,12 @@ void SyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR usleep(kCommissionPrepareTimeMs * 1000); - admin::DeviceManager::Instance().PairRemoteDevice(nodeId, payloadBuffer); + error = admin::PairingManager::Instance().PairDeviceWithCode(nodeId, payloadBuffer); + if (error != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to sync device: Node ID " ChipLogFormatX64 " with error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(nodeId), err.Format()); + } } else { From 048227b0b993624b0130182f1df47eda8e18a3b5 Mon Sep 17 00:00:00 2001 From: Amine Alami <43780877+Alami-Amine@users.noreply.github.com> Date: Fri, 22 Nov 2024 18:48:35 +0100 Subject: [PATCH 077/219] [Crypto] replacing OpenSSL-specific flag by new public API (#36608) This is a follow_up to #36386 based on a post-merge comment, - an OpenSSL-specific mInitialized flag was added to HASH_SHA256 to check if digest computation was initialised, which isn't used for other Crypto Backends - Fix: replace by a Public API `IsInitialized`, with its implementation for OpenSSL/BoringSSL --- src/crypto/CHIPCryptoPAL.h | 10 +++++++--- src/crypto/CHIPCryptoPALOpenSSL.cpp | 24 ++++++++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index 45e13f26bb..d2915f5d3c 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -900,6 +900,13 @@ class Hash_SHA256_stream */ CHIP_ERROR Begin(); + /** + * @brief check if the digest computation has been initialized. + * + * @return True if the context is correctly initialized; otherwise, false. + */ + bool IsInitialized(); + /** * @brief Add some data to the digest computation, updating internal state. * @@ -942,9 +949,6 @@ class Hash_SHA256_stream private: HashSHA256OpaqueContext mContext; -#if CHIP_CRYPTO_BORINGSSL || CHIP_CRYPTO_OPENSSL - bool mInitialized = false; -#endif }; class HKDF_sha diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index 033be44888..e1a8acb55f 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -449,7 +449,7 @@ static inline EVP_MD_CTX * to_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * co return *SafePointerCast(context); } -Hash_SHA256_stream::Hash_SHA256_stream() : mInitialized(false) +Hash_SHA256_stream::Hash_SHA256_stream() { set_inner_hash_evp_md_ctx(&mContext, nullptr); } @@ -470,14 +470,27 @@ CHIP_ERROR Hash_SHA256_stream::Begin() const int result = EVP_DigestInit_ex(mdctx, _digestForType(DigestType::SHA256), nullptr); VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL); - mInitialized = true; return CHIP_NO_ERROR; } +bool Hash_SHA256_stream::IsInitialized() +{ + EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); + VerifyOrReturnValue(mdctx != nullptr, false); + +// Verify that the EVP_MD_CTX is initialized to SHA256 (ensures that EVP_DigestInit_ex was called) +#if CHIP_CRYPTO_BORINGSSL + return EVP_MD_CTX_md(mdctx) == _digestForType(DigestType::SHA256); +#else + // EVP_MD_CTX_md() was Deprecated in OPENSSL 3.0; However, BoringSSL does not support EVP_MD_CTX_get0_md() yet + return EVP_MD_CTX_get0_md(mdctx) == _digestForType(DigestType::SHA256); +#endif +} + CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) { - VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear()); EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL); @@ -492,7 +505,7 @@ CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data) CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer) { - VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear()); EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); @@ -519,7 +532,7 @@ CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer) unsigned int size; VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL); - VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear()); EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); @@ -541,7 +554,6 @@ void Hash_SHA256_stream::Clear() EVP_MD_CTX_free(mdctx); set_inner_hash_evp_md_ctx(&mContext, nullptr); - mInitialized = false; OPENSSL_cleanse(this, sizeof(*this)); } From 7df9b146b3062744d7de87eed3e609f1b52f3fad Mon Sep 17 00:00:00 2001 From: Nivi Sarkar <55898241+nivi-apple@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:20:40 -0800 Subject: [PATCH 078/219] =?UTF-8?q?Add=20AsyncFacilitator=20to=20enable=20?= =?UTF-8?q?an=20async,=20event-driven,=20non-polling=20me=E2=80=A6=20(#293?= =?UTF-8?q?64)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add an AsyncTransferFacilitator that supports BDX transfer using an event driven approach rather than polling - Update the OTA provider darwin implementation to use the AsyncTransferFacilitator to transfer the OTA file using BDX * Editorial fixes * Restyled by whitespace * Restyled by clang-format * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Addresssed review comments * Restyle * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Address review comments * More fixes * Restyle * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Address more review comments * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Address review comments * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Fix restyled issues. * Add missing header * Address review comments. --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../CHIP/MTROTAImageTransferHandler.h | 79 +++ .../CHIP/MTROTAImageTransferHandler.mm | 401 ++++++++++++++ .../CHIP/MTROTAProviderDelegateBridge.h | 6 +- .../CHIP/MTROTAProviderDelegateBridge.mm | 509 ++---------------- .../CHIP/MTROTAUnsolicitedBDXMessageHandler.h | 74 +++ .../MTROTAUnsolicitedBDXMessageHandler.mm | 132 +++++ .../Matter.xcodeproj/project.pbxproj | 16 + .../bdx/AsyncTransferFacilitator.cpp | 196 +++++++ src/protocols/bdx/AsyncTransferFacilitator.h | 139 +++++ src/protocols/bdx/BUILD.gn | 2 + src/protocols/bdx/BdxTransferSession.cpp | 5 + src/protocols/bdx/BdxTransferSession.h | 2 + 12 files changed, 1088 insertions(+), 473 deletions(-) create mode 100644 src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h create mode 100644 src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm create mode 100644 src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h create mode 100644 src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm create mode 100644 src/protocols/bdx/AsyncTransferFacilitator.cpp create mode 100644 src/protocols/bdx/AsyncTransferFacilitator.h diff --git a/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h new file mode 100644 index 0000000000..bc45f6e0ae --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h @@ -0,0 +1,79 @@ +/** + * + * Copyright (c) 2024 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. + */ + +#import + +#include + +NS_ASSUME_NONNULL_BEGIN + +@class MTROTAImageTransferHandlerWrapper; + +/** + * This class handles the BDX events for a BDX transfer session. + * + * This object may be destroyed directly, when not processing some call it made, to interrupt the BDX + * transfer. Specifically, this has to be done if the fabric it's associated with is shut down. This + * method of interrupting the BDX transfer will not notify the peer that we are interrupting and it will + * keep waiting until it times out. + * + * If not otherwise destroyed, this object will destroy itself when the transfer completes. + */ +class MTROTAImageTransferHandler : public chip::bdx::AsyncResponder { +public: + MTROTAImageTransferHandler(chip::System::Layer * layer); + ~MTROTAImageTransferHandler(); + + chip::FabricIndex GetPeerFabricIndex() { return mPeer.GetFabricIndex(); } + +protected: + CHIP_ERROR OnMessageReceived(chip::Messaging::ExchangeContext * ec, const chip::PayloadHeader & payloadHeader, + chip::System::PacketBufferHandle && payload) override; + + void HandleTransferSessionOutput(chip::bdx::TransferSession::OutputEvent & event) override; + +private: + CHIP_ERROR Init(chip::Messaging::ExchangeContext * exchangeCtx); + + CHIP_ERROR OnTransferSessionBegin(const chip::bdx::TransferSession::OutputEventType event); + + CHIP_ERROR OnTransferSessionEnd(const chip::bdx::TransferSession::OutputEventType eventType); + + CHIP_ERROR OnBlockQuery(const chip::bdx::TransferSession::OutputEventType eventType, uint64_t bytesToSkip); + + chip::ScopedNodeId GetPeerScopedNodeId(chip::Messaging::ExchangeContext * exchangeCtx); + + void InvokeTransferSessionEndCallback(CHIP_ERROR error); + + void DestroySelf() override; + + // The scoped node id of the node with which the BDX session is established. + chip::ScopedNodeId mPeer; + + // The OTA provider delegate that is responding to the BDX transfer request. + id mDelegate = nil; + chip::System::Layer * mSystemLayer = nil; + + // The queue mDelegate must be called on. + dispatch_queue_t mDelegateNotificationQueue = nil; + + MTROTAImageTransferHandlerWrapper * mOTAImageTransferHandlerWrapper; + + bool mNeedToCallTransferSessionEnd = false; +}; + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm new file mode 100644 index 0000000000..efa84ef916 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm @@ -0,0 +1,401 @@ +/** + * + * Copyright (c) 2024 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. + */ + +#import "MTROTAImageTransferHandler.h" +#import "MTRDeviceControllerFactory_Internal.h" +#import "MTRDeviceController_Internal.h" +#import "MTRError_Internal.h" +#import "MTROTAUnsolicitedBDXMessageHandler.h" +#import "NSStringSpanConversion.h" + +using namespace chip; +using namespace chip::bdx; +using namespace chip::app; + +constexpr uint32_t kMaxBdxBlockSize = 1024; + +// Timeout for the BDX transfer session. The OTA Spec mandates this should be >= 5 minutes. +constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60); + +constexpr bdx::TransferRole kBdxRole = bdx::TransferRole::kSender; + +// An ARC-managed object that lets us do weak references to a MTROTAImageTransferHandler +// (which is a C++ object). +@interface MTROTAImageTransferHandlerWrapper : NSObject +- (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *)otaImageTransferHandler; + +// Non-atomic property since it's read or written only on the Matter queue. +@property (nonatomic, nullable, readwrite, assign) MTROTAImageTransferHandler * otaImageTransferHandler; +@end + +@implementation MTROTAImageTransferHandlerWrapper + +- (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *)otaImageTransferHandler +{ + if (self = [super init]) { + _otaImageTransferHandler = otaImageTransferHandler; + } + return self; +} +@end + +MTROTAImageTransferHandler::MTROTAImageTransferHandler(chip::System::Layer * layer) +{ + assertChipStackLockedByCurrentThread(); + + mSystemLayer = layer; + + MTROTAUnsolicitedBDXMessageHandler::GetInstance()->OnTransferHandlerCreated(this); + mOTAImageTransferHandlerWrapper = [[MTROTAImageTransferHandlerWrapper alloc] initWithMTROTAImageTransferHandler:this]; +} + +CHIP_ERROR MTROTAImageTransferHandler::Init(Messaging::ExchangeContext * exchangeCtx) +{ + assertChipStackLockedByCurrentThread(); + + mPeer = GetPeerScopedNodeId(exchangeCtx); + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + + mDelegate = controller.otaProviderDelegate; + mDelegateNotificationQueue = controller.otaProviderDelegateQueue; + + // We should have already checked that this controller supports OTA. + VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mDelegateNotificationQueue != nil, CHIP_ERROR_INCORRECT_STATE); + + BitFlags flags(bdx::TransferControlFlags::kReceiverDrive); + + return AsyncResponder::Init(mSystemLayer, exchangeCtx, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout); +} + +MTROTAImageTransferHandler::~MTROTAImageTransferHandler() +{ + assertChipStackLockedByCurrentThread(); + + if (mNeedToCallTransferSessionEnd) { + // TODO: Store the actual error involved in error cases, so we can pass the right thing here. + InvokeTransferSessionEndCallback(CHIP_ERROR_INTERNAL); + } + + MTROTAUnsolicitedBDXMessageHandler::GetInstance()->OnTransferHandlerDestroyed(this); + mOTAImageTransferHandlerWrapper.otaImageTransferHandler = nullptr; +} + +CHIP_ERROR MTROTAImageTransferHandler::OnTransferSessionBegin(const TransferSession::OutputEventType eventType) +{ + assertChipStackLockedByCurrentThread(); + + uint16_t fdl = 0; + auto fd = mTransfer.GetFileDesignator(fdl); + VerifyOrReturnError(fdl <= bdx::kMaxFileDesignatorLen, CHIP_ERROR_INCORRECT_STATE); + CharSpan fileDesignatorSpan(Uint8::to_const_char(fd), fdl); + + auto fileDesignator = AsString(fileDesignatorSpan); + if (fileDesignator == nil) { + return CHIP_ERROR_INCORRECT_STATE; + } + + auto offset = @(mTransfer.GetStartOffset()); + + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + + MTROTAImageTransferHandlerWrapper * __weak weakWrapper = mOTAImageTransferHandlerWrapper; + + auto completionHandler = ^(NSError * _Nullable error) { + [controller + asyncDispatchToMatterQueue:^() { + assertChipStackLockedByCurrentThread(); + + // Check if the OTA image transfer handler is still valid. If not, return from the completion handler. + MTROTAImageTransferHandlerWrapper * strongWrapper = weakWrapper; + if (!strongWrapper || !strongWrapper.otaImageTransferHandler) { + return; + } + + if (error != nil) { + CHIP_ERROR err = [MTRError errorToCHIPErrorCode:error]; + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + return; + } + + // bdx::TransferSession will automatically reject a transfer if there are no + // common supported control modes. It will also default to the smaller + // block size. + TransferSession::TransferAcceptData acceptData; + acceptData.ControlMode = bdx::TransferControlFlags::kReceiverDrive; + acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize(); + acceptData.StartOffset = mTransfer.GetStartOffset(); + acceptData.Length = mTransfer.GetTransferLength(); + + CHIP_ERROR err = mTransfer.AcceptTransfer(acceptData); + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + errorHandler:^(NSError *) { + // Not much we can do here, but if the controller is shut down we + // should already have been destroyed anyway. + }]; + }; + + auto nodeId = @(mPeer.GetNodeId()); + + auto strongDelegate = mDelegate; + auto delegateQueue = mDelegateNotificationQueue; + if (strongDelegate == nil || delegateQueue == nil) { + LogErrorOnFailure(CHIP_ERROR_INCORRECT_STATE); + return CHIP_ERROR_INCORRECT_STATE; + } + + dispatch_async(delegateQueue, ^{ + if ([strongDelegate respondsToSelector:@selector + (handleBDXTransferSessionBeginForNodeID:controller:fileDesignator:offset:completion:)]) { + [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId + controller:controller + fileDesignator:fileDesignator + offset:offset + completion:completionHandler]; + } else { + [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId + controller:controller + fileDesignator:fileDesignator + offset:offset + completionHandler:completionHandler]; + } + }); + mNeedToCallTransferSessionEnd = true; + return CHIP_NO_ERROR; +} + +void MTROTAImageTransferHandler::InvokeTransferSessionEndCallback(CHIP_ERROR error) +{ + assertChipStackLockedByCurrentThread(); + + mNeedToCallTransferSessionEnd = false; + + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturn(controller != nil); + auto nodeId = @(mPeer.GetNodeId()); + + auto strongDelegate = mDelegate; + auto delegateQueue = mDelegateNotificationQueue; + if (strongDelegate == nil || delegateQueue == nil) { + LogErrorOnFailure(CHIP_ERROR_INCORRECT_STATE); + return; + } + + auto nsError = [MTRError errorForCHIPErrorCode:error]; + if ([strongDelegate respondsToSelector:@selector(handleBDXTransferSessionEndForNodeID:controller:error:)]) { + dispatch_async(delegateQueue, ^{ + [strongDelegate handleBDXTransferSessionEndForNodeID:nodeId + controller:controller + error:nsError]; + }); + } +} + +CHIP_ERROR MTROTAImageTransferHandler::OnTransferSessionEnd(const TransferSession::OutputEventType eventType) +{ + assertChipStackLockedByCurrentThread(); + + CHIP_ERROR error = CHIP_NO_ERROR; + if (eventType == TransferSession::OutputEventType::kTransferTimeout) { + error = CHIP_ERROR_TIMEOUT; + } else if (eventType != TransferSession::OutputEventType::kAckEOFReceived) { + error = CHIP_ERROR_INTERNAL; + } + + InvokeTransferSessionEndCallback(error); + + if (error == CHIP_NO_ERROR) { + NotifyEventHandled(eventType, error); + } + return error; +} + +CHIP_ERROR MTROTAImageTransferHandler::OnBlockQuery(const TransferSession::OutputEventType eventType, uint64_t bytesToSkip) +{ + assertChipStackLockedByCurrentThread(); + + auto blockSize = @(mTransfer.GetTransferBlockSize()); + auto blockIndex = @(mTransfer.GetNextBlockNum()); + + auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mPeer.GetFabricIndex()]; + VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); + + MTROTAImageTransferHandlerWrapper * __weak weakWrapper = mOTAImageTransferHandlerWrapper; + + auto completionHandler = ^(NSData * _Nullable data, BOOL isEOF) { + [controller + asyncDispatchToMatterQueue:^() { + assertChipStackLockedByCurrentThread(); + + // Check if the OTA image transfer handler is still valid. If not, return from the completion handler. + MTROTAImageTransferHandlerWrapper * strongWrapper = weakWrapper; + if (!strongWrapper || !strongWrapper.otaImageTransferHandler) { + return; + } + + if (data == nil) { + NotifyEventHandled(eventType, CHIP_ERROR_INCORRECT_STATE); + return; + } + + TransferSession::BlockData blockData; + blockData.Data = static_cast([data bytes]); + blockData.Length = static_cast([data length]); + blockData.IsEof = isEOF; + + CHIP_ERROR err = mTransfer.PrepareBlock(blockData); + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + errorHandler:^(NSError *) { + // Not much we can do here, but if the controller is shut down we + // should already have been destroyed anyway. + }]; + }; + + // TODO Handle MaxLength + + auto nodeId = @(mPeer.GetNodeId()); + + auto strongDelegate = mDelegate; + auto delegateQueue = mDelegateNotificationQueue; + if (strongDelegate == nil || delegateQueue == nil) { + LogErrorOnFailure(CHIP_ERROR_INCORRECT_STATE); + return CHIP_ERROR_INCORRECT_STATE; + } + + dispatch_async(delegateQueue, ^{ + if ([strongDelegate respondsToSelector:@selector(handleBDXQueryForNodeID: + controller:blockSize:blockIndex:bytesToSkip:completion:)]) { + [strongDelegate handleBDXQueryForNodeID:nodeId + controller:controller + blockSize:blockSize + blockIndex:blockIndex + bytesToSkip:@(bytesToSkip) + completion:completionHandler]; + } else { + [strongDelegate handleBDXQueryForNodeID:nodeId + controller:controller + blockSize:blockSize + blockIndex:blockIndex + bytesToSkip:@(bytesToSkip) + completionHandler:completionHandler]; + } + }); + return CHIP_NO_ERROR; +} + +void MTROTAImageTransferHandler::HandleTransferSessionOutput(TransferSession::OutputEvent & event) +{ + VerifyOrReturn(mDelegate != nil); + + TransferSession::OutputEventType eventType = event.EventType; + + ChipLogError(BDX, "OutputEvent type: %s", event.ToString(eventType)); + + CHIP_ERROR err = CHIP_NO_ERROR; + switch (event.EventType) { + case TransferSession::OutputEventType::kInitReceived: + err = OnTransferSessionBegin(eventType); + if (err != CHIP_NO_ERROR) { + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + break; + case TransferSession::OutputEventType::kStatusReceived: + ChipLogError(BDX, "Got StatusReport %x", static_cast(event.statusData.statusCode)); + [[fallthrough]]; + case TransferSession::OutputEventType::kAckEOFReceived: + case TransferSession::OutputEventType::kInternalError: + case TransferSession::OutputEventType::kTransferTimeout: + err = OnTransferSessionEnd(eventType); + if (err != CHIP_NO_ERROR) { + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + break; + case TransferSession::OutputEventType::kQueryWithSkipReceived: + case TransferSession::OutputEventType::kQueryReceived: { + uint64_t bytesToSkip = (eventType == TransferSession::OutputEventType::kQueryWithSkipReceived ? event.bytesToSkip.BytesToSkip : 0); + err = OnBlockQuery(eventType, bytesToSkip); + if (err != CHIP_NO_ERROR) { + LogErrorOnFailure(err); + NotifyEventHandled(eventType, err); + } + break; + } + case TransferSession::OutputEventType::kNone: + case TransferSession::OutputEventType::kAckReceived: + case TransferSession::OutputEventType::kAcceptReceived: + case TransferSession::OutputEventType::kBlockReceived: + default: + // Should never happen since this implements an OTA provider in BDX Receiver role. + chipDie(); + break; + } +} + +void MTROTAImageTransferHandler::DestroySelf() +{ + assertChipStackLockedByCurrentThread(); + + delete this; +} + +ScopedNodeId MTROTAImageTransferHandler::GetPeerScopedNodeId(Messaging::ExchangeContext * ec) +{ + auto sessionHandle = ec->GetSessionHandle(); + + if (sessionHandle->IsSecureSession()) { + return sessionHandle->AsSecureSession()->GetPeer(); + } else if (sessionHandle->IsGroupSession()) { + return sessionHandle->AsIncomingGroupSession()->GetPeer(); + } + return ScopedNodeId(); +} + +CHIP_ERROR MTROTAImageTransferHandler::OnMessageReceived( + Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, System::PacketBufferHandle && payload) +{ + assertChipStackLockedByCurrentThread(); + + ChipLogProgress(BDX, "MTROTAImageTransferHandler: OnMessageReceived: message " ChipLogFormatMessageType " protocol " ChipLogFormatProtocolId, + payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID())); + + VerifyOrReturnError(ec != nullptr, CHIP_ERROR_INCORRECT_STATE); + CHIP_ERROR err; + + // If we receive a ReceiveInit message, then we prepare for transfer. + // + // If init succeeds, or is not needed, we send the message to the AsyncTransferFacilitator for processing. + if (payloadHeader.HasMessageType(MessageType::ReceiveInit)) { + err = Init(ec); + if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "OnMessageReceived: Failed to prepare for transfer for BDX: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + } + + // Send the message to the AsyncFacilitator to drive the BDX session state machine. + AsyncTransferFacilitator::OnMessageReceived(ec, payloadHeader, std::move(payload)); + return err; +} diff --git a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h index 3d70954bb9..1b7a6f1bc7 100644 --- a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h +++ b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.h @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 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. @@ -18,6 +18,7 @@ #import #import "MTRDeviceController_Concrete.h" +#import "MTROTAUnsolicitedBDXMessageHandler.h" #include @@ -67,6 +68,9 @@ class MTROTAProviderDelegateBridge : public chip::app::Clusters::OTAProviderDele static void ConvertToNotifyUpdateAppliedParams( const chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::DecodableType & commandData, MTROTASoftwareUpdateProviderClusterNotifyUpdateAppliedParams * commandParams); + +protected: + MTROTAUnsolicitedBDXMessageHandler mOtaUnsolicitedBDXMsgHandler; }; NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm index 8729ac2a0f..a0f831cc83 100644 --- a/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm +++ b/src/darwin/Framework/CHIP/MTROTAProviderDelegateBridge.mm @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2022 Project CHIP Authors + * Copyright (c) 2022-2024 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. @@ -20,6 +20,7 @@ #import "MTRCommandPayloadsObjC.h" #import "MTRDeviceControllerFactory_Internal.h" #import "MTRDeviceController_Internal.h" +#import "MTRError_Internal.h" #import "NSDataSpanConversion.h" #import "NSStringSpanConversion.h" @@ -30,11 +31,10 @@ #include #include -#include #include #include +#include #include -#include using namespace chip; using namespace chip::app; @@ -42,13 +42,9 @@ using namespace chip::bdx; using Protocols::InteractionModel::Status; -// TODO Expose a method onto the delegate to make that configurable. -constexpr uint32_t kMaxBdxBlockSize = 1024; -constexpr uint32_t kMaxBDXURILen = 256; +namespace { -// Since the BDX timeout is 5 minutes and we are starting this after query image is available and before the BDX init comes, -// we just double the timeout to give enough time for the BDX init to come in a reasonable amount of time. -constexpr System::Clock::Timeout kBdxInitReceivedTimeout = System::Clock::Seconds16(10 * 60); +constexpr uint32_t kMaxBDXURILen = 256; // Time in seconds after which the requestor should retry calling query image if // busy status is receieved. The spec minimum is 2 minutes, but in practice OTA @@ -58,457 +54,44 @@ // OTA. constexpr uint32_t kDelayedActionTimeSeconds = 600; -constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60); // OTA Spec mandates >= 5 minutes -constexpr System::Clock::Timeout kBdxPollIntervalMs = System::Clock::Milliseconds32(50); -constexpr bdx::TransferRole kBdxRole = bdx::TransferRole::kSender; - -class BdxOTASender : public bdx::Responder { -public: - BdxOTASender() {}; - - CHIP_ERROR PrepareForTransfer(FabricIndex fabricIndex, NodeId nodeId) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mExchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - - ReturnErrorOnFailure(ConfigureState(fabricIndex, nodeId)); - - BitFlags flags(bdx::TransferControlFlags::kReceiverDrive); - return Responder::PrepareForTransfer(mSystemLayer, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollIntervalMs); - } - - CHIP_ERROR Init(System::Layer * systemLayer, Messaging::ExchangeManager * exchangeMgr) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mSystemLayer == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mExchangeMgr == nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(exchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - - exchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id, this); - - mSystemLayer = systemLayer; - mExchangeMgr = exchangeMgr; - - return CHIP_NO_ERROR; - } - - CHIP_ERROR Shutdown() - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mExchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); - - mExchangeMgr->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id); - ResetState(CHIP_ERROR_CANCELLED); - - mExchangeMgr = nullptr; - mSystemLayer = nullptr; - - return CHIP_NO_ERROR; - } - - void ControllerShuttingDown(MTRDeviceController_Concrete * controller) - { - assertChipStackLockedByCurrentThread(); - - if (mInitialized && mFabricIndex.Value() == controller.fabricIndex) { - ResetState(CHIP_ERROR_CANCELLED); - } - } - - void ResetState(CHIP_ERROR error) - { - assertChipStackLockedByCurrentThread(); - if (mNodeId.HasValue() && mFabricIndex.HasValue()) { - ChipLogProgress(Controller, - "Resetting state for OTA Provider; no longer providing an update for node id 0x" ChipLogFormatX64 - ", fabric index %u", - ChipLogValueX64(mNodeId.Value()), mFabricIndex.Value()); - - if (mTransferStarted) { - auto controller = [MTRDeviceControllerFactory.sharedInstance runningControllerForFabricIndex:mFabricIndex.Value()]; - if (controller) { - auto nodeId = @(mNodeId.Value()); - auto strongDelegate = mDelegate; - if ([strongDelegate respondsToSelector:@selector(handleBDXTransferSessionEndForNodeID:controller:error:)]) { - dispatch_async(mDelegateNotificationQueue, ^{ - [strongDelegate handleBDXTransferSessionEndForNodeID:nodeId - controller:controller - error:[MTRError errorForCHIPErrorCode:error]]; - }); - } - } else { - ChipLogError(Controller, "Not notifying delegate of BDX Transfer Session End, controller is not running"); - } - } - } else { - ChipLogProgress(Controller, "Resetting state for OTA Provider"); - } - if (mSystemLayer) { - mSystemLayer->CancelTimer(HandleBdxInitReceivedTimeoutExpired, this); - } - // TODO: Check if this can be removed. It seems like we can close the exchange context and reset transfer regardless. - if (!mInitialized) { - return; - } - Responder::ResetTransfer(); - ++mTransferGeneration; - mFabricIndex.ClearValue(); - mNodeId.ClearValue(); - - if (mExchangeCtx != nullptr) { - mExchangeCtx->Close(); - mExchangeCtx = nullptr; - } - - mDelegate = nil; - mDelegateNotificationQueue = nil; - - mInitialized = false; - mTransferStarted = false; - } - -private: - /** - * Timer callback called when we don't receive a BDX init within a reasonable time after a successful QueryImage response. - */ - static void HandleBdxInitReceivedTimeoutExpired(chip::System::Layer * systemLayer, void * state) - { - VerifyOrReturn(state != nullptr); - static_cast(state)->ResetState(CHIP_ERROR_TIMEOUT); - } - - CHIP_ERROR OnMessageToSend(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); - - Messaging::SendFlags sendFlags; - - // All messages sent from the Sender expect a response, except for a StatusReport which would indicate an error and - // the end of the transfer. - if (!event.msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) { - sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse); - } - - auto & msgTypeData = event.msgTypeData; - // If there's an error sending the message, close the exchange and call ResetState. - // TODO: If we can remove the !mInitialized check in ResetState(), just calling ResetState() will suffice here. - CHIP_ERROR err - = mExchangeCtx->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(event.MsgData), sendFlags); - if (err != CHIP_NO_ERROR) { - mExchangeCtx->Close(); - mExchangeCtx = nullptr; - ResetState(err); - } else if (msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) { - // If the send was successful for a status report, since we are not expecting a response the exchange context is - // already closed. We need to null out the reference to avoid having a dangling pointer. - mExchangeCtx = nullptr; - ResetState(CHIP_ERROR_INTERNAL); - } - return err; - } - - CHIP_ERROR OnTransferSessionBegin(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - // Once we receive the BDX init, cancel the BDX Init timeout and start the BDX session - if (mSystemLayer) { - mSystemLayer->CancelTimer(HandleBdxInitReceivedTimeoutExpired, this); - } - - VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); - uint16_t fdl = 0; - auto fd = mTransfer.GetFileDesignator(fdl); - VerifyOrReturnError(fdl <= bdx::kMaxFileDesignatorLen, CHIP_ERROR_INVALID_ARGUMENT); - CharSpan fileDesignatorSpan(Uint8::to_const_char(fd), fdl); - - auto fileDesignator = AsString(fileDesignatorSpan); - if (fileDesignator == nil) { - return CHIP_ERROR_INCORRECT_STATE; - } - - auto offset = @(mTransfer.GetStartOffset()); - - auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; - VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); - - auto transferGeneration = mTransferGeneration; - - auto completionHandler = ^(NSError * _Nullable error) { - [controller - asyncDispatchToMatterQueue:^() { - assertChipStackLockedByCurrentThread(); - - if (!mInitialized || mTransferGeneration != transferGeneration) { - // Callback for a stale transfer. - return; - } - - if (error != nil) { - CHIP_ERROR err = [MTRError errorToCHIPErrorCode:error]; - LogErrorOnFailure(err); - LogErrorOnFailure(mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err))); - return; - } - - // bdx::TransferSession will automatically reject a transfer if there are no - // common supported control modes. It will also default to the smaller - // block size. - TransferSession::TransferAcceptData acceptData; - acceptData.ControlMode = bdx::TransferControlFlags::kReceiverDrive; - acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize(); - acceptData.StartOffset = mTransfer.GetStartOffset(); - acceptData.Length = mTransfer.GetTransferLength(); - - LogErrorOnFailure(mTransfer.AcceptTransfer(acceptData)); - } - errorHandler:^(NSError *) { - // Not much we can do here - }]; - }; - - mTransferStarted = true; - auto nodeId = @(mNodeId.Value()); - auto strongDelegate = mDelegate; - dispatch_async(mDelegateNotificationQueue, ^{ - if ([strongDelegate respondsToSelector:@selector(handleBDXTransferSessionBeginForNodeID:controller:fileDesignator:offset:completion:)]) { - [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId - controller:controller - fileDesignator:fileDesignator - offset:offset - completion:completionHandler]; - } else { - [strongDelegate handleBDXTransferSessionBeginForNodeID:nodeId - controller:controller - fileDesignator:fileDesignator - offset:offset - completionHandler:completionHandler]; - } - }); - - return CHIP_NO_ERROR; - } - - CHIP_ERROR OnTransferSessionEnd(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); - - CHIP_ERROR error = CHIP_NO_ERROR; - if (event.EventType == TransferSession::OutputEventType::kTransferTimeout) { - error = CHIP_ERROR_TIMEOUT; - } else if (event.EventType != TransferSession::OutputEventType::kAckEOFReceived) { - error = CHIP_ERROR_INTERNAL; - } - - ResetState(error); // will notify the delegate - return CHIP_NO_ERROR; - } - - CHIP_ERROR OnBlockQuery(TransferSession::OutputEvent & event) - { - assertChipStackLockedByCurrentThread(); - - VerifyOrReturnError(mFabricIndex.HasValue(), CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mNodeId.HasValue(), CHIP_ERROR_INCORRECT_STATE); - - auto blockSize = @(mTransfer.GetTransferBlockSize()); - auto blockIndex = @(mTransfer.GetNextBlockNum()); - - auto bytesToSkip = @(0); - if (event.EventType == TransferSession::OutputEventType::kQueryWithSkipReceived) { - bytesToSkip = @(event.bytesToSkip.BytesToSkip); - } - - auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:mFabricIndex.Value()]; - VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); - - auto transferGeneration = mTransferGeneration; - - auto completionHandler = ^(NSData * _Nullable data, BOOL isEOF) { - [controller - asyncDispatchToMatterQueue:^() { - assertChipStackLockedByCurrentThread(); - - if (!mInitialized || mTransferGeneration != transferGeneration) { - // Callback for a stale transfer. - return; - } - - if (data == nil) { - LogErrorOnFailure(mTransfer.AbortTransfer(bdx::StatusCode::kUnknown)); - return; - } - - TransferSession::BlockData blockData; - blockData.Data = static_cast([data bytes]); - blockData.Length = static_cast([data length]); - blockData.IsEof = isEOF; - - CHIP_ERROR err = mTransfer.PrepareBlock(blockData); - if (CHIP_NO_ERROR != err) { - LogErrorOnFailure(err); - LogErrorOnFailure(mTransfer.AbortTransfer(bdx::StatusCode::kUnknown)); - } - } - errorHandler:^(NSError *) { - // Not much we can do here - }]; - }; - - // TODO Handle MaxLength - - auto nodeId = @(mNodeId.Value()); - - auto strongDelegate = mDelegate; - dispatch_async(mDelegateNotificationQueue, ^{ - if ([strongDelegate respondsToSelector:@selector(handleBDXQueryForNodeID:controller:blockSize:blockIndex:bytesToSkip:completion:)]) { - [strongDelegate handleBDXQueryForNodeID:nodeId - controller:controller - blockSize:blockSize - blockIndex:blockIndex - bytesToSkip:bytesToSkip - completion:completionHandler]; - } else { - [strongDelegate handleBDXQueryForNodeID:nodeId - controller:controller - blockSize:blockSize - blockIndex:blockIndex - bytesToSkip:bytesToSkip - completionHandler:completionHandler]; - } - }); - - return CHIP_NO_ERROR; - } - - void HandleTransferSessionOutput(TransferSession::OutputEvent & event) override - { - VerifyOrReturn(mDelegate != nil); - - CHIP_ERROR err = CHIP_NO_ERROR; - switch (event.EventType) { - case TransferSession::OutputEventType::kInitReceived: - err = OnTransferSessionBegin(event); - if (err != CHIP_NO_ERROR) { - LogErrorOnFailure(mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err))); - } - break; - case TransferSession::OutputEventType::kStatusReceived: - ChipLogError(BDX, "Got StatusReport %x", static_cast(event.statusData.statusCode)); - [[fallthrough]]; - case TransferSession::OutputEventType::kAckEOFReceived: - case TransferSession::OutputEventType::kInternalError: - case TransferSession::OutputEventType::kTransferTimeout: - err = OnTransferSessionEnd(event); - break; - case TransferSession::OutputEventType::kQueryWithSkipReceived: - case TransferSession::OutputEventType::kQueryReceived: - err = OnBlockQuery(event); - break; - case TransferSession::OutputEventType::kMsgToSend: - err = OnMessageToSend(event); - break; - case TransferSession::OutputEventType::kNone: - case TransferSession::OutputEventType::kAckReceived: - // Nothing to do. - break; - case TransferSession::OutputEventType::kAcceptReceived: - case TransferSession::OutputEventType::kBlockReceived: - default: - // Should never happens. - chipDie(); - break; - } - LogErrorOnFailure(err); - } - - CHIP_ERROR ConfigureState(chip::FabricIndex fabricIndex, chip::NodeId nodeId) - { - assertChipStackLockedByCurrentThread(); - - if (mInitialized) { - // Prevent a new node connection since another is active. - VerifyOrReturnError(mFabricIndex.Value() == fabricIndex && mNodeId.Value() == nodeId, CHIP_ERROR_BUSY); - - // Reset stale connection from the same Node if exists. - ResetState(CHIP_ERROR_CANCELLED); - } - - auto * controller = [[MTRDeviceControllerFactory sharedInstance] runningControllerForFabricIndex:fabricIndex]; - VerifyOrReturnError(controller != nil, CHIP_ERROR_INCORRECT_STATE); - - mDelegate = controller.otaProviderDelegate; - mDelegateNotificationQueue = controller.otaProviderDelegateQueue; - - // We should have already checked that this controller supports OTA. - VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(mDelegateNotificationQueue != nil, CHIP_ERROR_INCORRECT_STATE); - - // Start a timer to track whether we receive a BDX init after a successful query image in a reasonable amount of time - CHIP_ERROR err = mSystemLayer->StartTimer(kBdxInitReceivedTimeout, HandleBdxInitReceivedTimeoutExpired, this); - LogErrorOnFailure(err); - - ReturnErrorOnFailure(err); - - mFabricIndex.SetValue(fabricIndex); - mNodeId.SetValue(nodeId); - - mInitialized = true; - - return CHIP_NO_ERROR; - } - - bool mInitialized = false; - bool mTransferStarted = false; - Optional mFabricIndex; - Optional mNodeId; - id mDelegate = nil; - dispatch_queue_t mDelegateNotificationQueue = nil; - Messaging::ExchangeManager * mExchangeMgr = nullptr; - - // Since we are a singleton, we get reused across transfers, but also have - // async calls that can happen. The transfer generation keeps track of - // which transfer we are currently doing, so we can ignore async calls - // attached to no-longer-running transfers. - uint64_t mTransferGeneration = 0; -}; - -namespace { -Global gOtaSender; - -NSInteger constexpr kOtaProviderEndpoint = 0; +NSInteger const kOtaProviderEndpoint = 0; } // anonymous namespace -MTROTAProviderDelegateBridge::MTROTAProviderDelegateBridge() { Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, this); } +MTROTAProviderDelegateBridge::MTROTAProviderDelegateBridge() +{ + Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, this); +} MTROTAProviderDelegateBridge::~MTROTAProviderDelegateBridge() { - gOtaSender->ResetState(CHIP_ERROR_CANCELLED); Clusters::OTAProvider::SetDelegate(kOtaProviderEndpoint, nullptr); } CHIP_ERROR MTROTAProviderDelegateBridge::Init(System::Layer * systemLayer, Messaging::ExchangeManager * exchangeManager) { - return gOtaSender->Init(systemLayer, exchangeManager); + assertChipStackLockedByCurrentThread(); + + VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INCORRECT_STATE); + + CHIP_ERROR err = mOtaUnsolicitedBDXMsgHandler.Init(systemLayer, exchangeManager); + if (err != CHIP_NO_ERROR) { + ChipLogError(Controller, "Failed to initialize the unsolicited BDX Message handler with err %s", err.AsString()); + } + return err; } -void MTROTAProviderDelegateBridge::Shutdown() { gOtaSender->Shutdown(); } +void MTROTAProviderDelegateBridge::Shutdown() +{ + assertChipStackLockedByCurrentThread(); + + mOtaUnsolicitedBDXMsgHandler.Shutdown(); +} void MTROTAProviderDelegateBridge::ControllerShuttingDown(MTRDeviceController_Concrete * controller) { - gOtaSender->ControllerShuttingDown(controller); + assertChipStackLockedByCurrentThread(); + + mOtaUnsolicitedBDXMsgHandler.ControllerShuttingDown(controller); } namespace { @@ -611,7 +194,6 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath return; } - auto fabricIndex = commandObj->GetAccessingFabricIndex(); auto ourNodeId = commandObj->GetExchangeContext()->GetSessionHandle()->AsSecureSession()->GetLocalScopedNodeId(); auto * commandParams = [[MTROTASoftwareUpdateProviderClusterQueryImageParams alloc] init]; @@ -667,42 +249,25 @@ bool GetPeerNodeInfo(CommandHandler * commandHandler, const ConcreteCommandPath return; } - // If there is an update available, try to prepare for a transfer. - CHIP_ERROR err = gOtaSender->PrepareForTransfer(fabricIndex, nodeId); - if (CHIP_NO_ERROR != err) { - - // Handle busy error separately as we have a query image response status that maps to busy - if (err == CHIP_ERROR_BUSY) { - ChipLogError( - Controller, "Responding with Busy due to being in the middle of handling another BDX transfer"); - Commands::QueryImageResponse::Type response; - response.status = static_cast(MTROTASoftwareUpdateProviderStatusBusy); - response.delayedActionTime.SetValue(delegateResponse.delayedActionTime.ValueOr(kDelayedActionTimeSeconds)); - handler->AddResponse(cachedCommandPath, response); - handle.Release(); - // We do not reset state when we get the busy error because that means we are locked in a BDX transfer - // session with another requestor when we get this query image request. We do not want to interrupt the - // ongoing transfer instead just respond to the second requestor with a busy status and a delayedActionTime - // in which the requestor can retry. - return; - } - LogErrorOnFailure(err); - handler->AddStatus(cachedCommandPath, StatusIB(err).mStatus); + // If the MTROTAUnsolicitedBDXMessageHandler already has an ongoing transfer, send busy error. + if (MTROTAUnsolicitedBDXMessageHandler::GetInstance()->IsInAnOngoingTransfer()) { + ChipLogError( + Controller, "Responding with Busy due to being in the middle of handling another BDX transfer"); + Commands::QueryImageResponse::Type response; + response.status = static_cast(MTROTASoftwareUpdateProviderStatusBusy); + response.delayedActionTime.SetValue(delegateResponse.delayedActionTime.ValueOr(kDelayedActionTimeSeconds)); + handler->AddResponse(cachedCommandPath, response); handle.Release(); - // We need to reset state here to clean up any initialization we might have done including starting the BDX - // timeout timer while preparing for transfer if any failure occurs afterwards. - gOtaSender->ResetState(err); return; } char uriBuffer[kMaxBDXURILen]; MutableCharSpan uri(uriBuffer); - err = bdx::MakeURI(ourNodeId.GetNodeId(), AsCharSpan(data.imageURI), uri); + CHIP_ERROR err = bdx::MakeURI(ourNodeId.GetNodeId(), AsCharSpan(data.imageURI), uri); if (CHIP_NO_ERROR != err) { LogErrorOnFailure(err); handler->AddStatus(cachedCommandPath, StatusIB(err).mStatus); handle.Release(); - gOtaSender->ResetState(err); return; } delegateResponse.imageURI.SetValue(uri); diff --git a/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h new file mode 100644 index 0000000000..83a5f4443c --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.h @@ -0,0 +1,74 @@ +/** + * + * Copyright (c) 2024 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. + */ + +#import "MTRDeviceController_Concrete.h" +#import "MTROTAImageTransferHandler.h" +#import + +#include +#include + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class defines a handler that can listen for all unsolicited BDX messages. + * + * When it receives a BDX ReceiveInit message from a node, it creates a new + * MTROTAImageTransferHandler object as the exchange delegate that will + * handle the transfer. + * + * In all other cases, it fails out so that there is no exchange delegate created, + * which means the message is potentially acked, but does not get a response. + */ +class MTROTAUnsolicitedBDXMessageHandler : public chip::Messaging::UnsolicitedMessageHandler +{ +public: + MTROTAUnsolicitedBDXMessageHandler() : mExchangeMgr(nullptr) { sInstance = this; } + + ~MTROTAUnsolicitedBDXMessageHandler() {} + + static MTROTAUnsolicitedBDXMessageHandler * GetInstance(); + + CHIP_ERROR Init(chip::System::Layer * systemLayer, chip::Messaging::ExchangeManager * exchangeManager); + + bool IsInAnOngoingTransfer(); + + void OnTransferHandlerCreated(MTROTAImageTransferHandler * imageTransferHandler); + + void OnTransferHandlerDestroyed(MTROTAImageTransferHandler * imageTransferHandler); + + void Shutdown(); + + void ControllerShuttingDown(MTRDeviceController_Concrete * controller); + +private: + CHIP_ERROR OnUnsolicitedMessageReceived(const chip::PayloadHeader & payloadHeader, const chip::SessionHandle & session, + chip::Messaging::ExchangeDelegate * _Nonnull & newDelegate) override; + + void OnExchangeCreationFailed(chip::Messaging::ExchangeDelegate * _Nonnull delegate) override; + + // TODO: #36181 - Have a set of MTROTAImageTransferHandler objects. + MTROTAImageTransferHandler * _Nullable mOTAImageTransferHandler = nullptr; + + chip::System::Layer * mSystemLayer; + + chip::Messaging::ExchangeManager * mExchangeMgr; + + static MTROTAUnsolicitedBDXMessageHandler * sInstance; +}; + +NS_ASSUME_NONNULL_END diff --git a/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm new file mode 100644 index 0000000000..2e3e5c2293 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTROTAUnsolicitedBDXMessageHandler.mm @@ -0,0 +1,132 @@ +/** + * + * Copyright (c) 2024 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. + */ + +#import "MTROTAUnsolicitedBDXMessageHandler.h" +#import "MTRDeviceController_Internal.h" + +#include + +using namespace chip; +using namespace chip::Messaging; +using namespace chip::bdx; + +MTROTAUnsolicitedBDXMessageHandler * MTROTAUnsolicitedBDXMessageHandler::sInstance = nullptr; + +CHIP_ERROR MTROTAUnsolicitedBDXMessageHandler::Init(System::Layer * systemLayer, ExchangeManager * exchangeManager) +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + mSystemLayer = systemLayer; + mExchangeMgr = exchangeManager; + return mExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id, this); +} + +MTROTAUnsolicitedBDXMessageHandler * MTROTAUnsolicitedBDXMessageHandler::GetInstance() +{ + return sInstance; +} + +void MTROTAUnsolicitedBDXMessageHandler::Shutdown() +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrReturn(mExchangeMgr != nullptr); + mExchangeMgr->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id); + + VerifyOrReturn(mOTAImageTransferHandler != nullptr); + + delete mOTAImageTransferHandler; + mOTAImageTransferHandler = nullptr; +} + +void MTROTAUnsolicitedBDXMessageHandler::ControllerShuttingDown(MTRDeviceController_Concrete * controller) +{ + assertChipStackLockedByCurrentThread(); + + VerifyOrReturn(mOTAImageTransferHandler != nullptr); + + FabricIndex peerFabricIndex = mOTAImageTransferHandler->GetPeerFabricIndex(); + VerifyOrReturn(peerFabricIndex != kUndefinedFabricIndex); + + if (controller.fabricIndex == peerFabricIndex) { + delete mOTAImageTransferHandler; + mOTAImageTransferHandler = nullptr; + } +} + +bool MTROTAUnsolicitedBDXMessageHandler::IsInAnOngoingTransfer() +{ + return (mOTAImageTransferHandler != nullptr); +} + +CHIP_ERROR MTROTAUnsolicitedBDXMessageHandler::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, const SessionHandle & session, + ExchangeDelegate * _Nonnull & newDelegate) +{ + assertChipStackLockedByCurrentThread(); + + ChipLogDetail(BDX, "MTROTAUnsolicitedBDXMessageHandler: OnUnsolicitedMessageReceived: message " ChipLogFormatMessageType " protocol " ChipLogFormatProtocolId, + payloadHeader.GetMessageType(), ChipLogValueProtocolId(payloadHeader.GetProtocolID())); + + if (IsInAnOngoingTransfer()) { + ChipLogDetail(BDX, "Already in an ongoing transfer. Return"); + return CHIP_ERROR_BUSY; + } + + VerifyOrReturnError(mExchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); + + // Only proceed if there is a valid fabric index for the SessionHandle. + if (session->IsSecureSession() && session->AsSecureSession() != nullptr && session->AsSecureSession()->GetFabricIndex() != kUndefinedFabricIndex) { + + // If we receive a ReceiveInit BDX message, create a new MTROTAImageTransferHandler and register it + // as the handler for all BDX messages that will come over this exchange. + if (payloadHeader.HasMessageType(MessageType::ReceiveInit)) { + newDelegate = new MTROTAImageTransferHandler(mSystemLayer); + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_INCORRECT_STATE; +} + +void MTROTAUnsolicitedBDXMessageHandler::OnExchangeCreationFailed(ExchangeDelegate * delegate) +{ + assertChipStackLockedByCurrentThread(); + auto * otaTransferHandler = static_cast(delegate); + VerifyOrReturn(otaTransferHandler != nullptr); + + delete otaTransferHandler; +} + +void MTROTAUnsolicitedBDXMessageHandler::OnTransferHandlerCreated(MTROTAImageTransferHandler * imageTransferHandler) +{ + assertChipStackLockedByCurrentThread(); + + // TODO: #36181 - Store the imageTransferHandler in a set of MTROTAImageTransferHandler objects. + mOTAImageTransferHandler = imageTransferHandler; +} + +void MTROTAUnsolicitedBDXMessageHandler::OnTransferHandlerDestroyed(MTROTAImageTransferHandler * imageTransferHandler) +{ + assertChipStackLockedByCurrentThread(); + + // TODO: #36181 - Remove the object matching imageTransferHandler in the set of MTROTAImageTransferHandler objects. + if (mOTAImageTransferHandler == imageTransferHandler) { + mOTAImageTransferHandler = nullptr; + } +} diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index fa1634da4b..13f0eb8e20 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -422,6 +422,10 @@ B4FCD5722B603A6300832859 /* DownloadLogCommand.mm in Sources */ = {isa = PBXBuildFile; fileRef = B4FCD56F2B603A6300832859 /* DownloadLogCommand.mm */; }; B4FCD5732B611EB300832859 /* MTRDiagnosticLogsDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = B4C8E6B32B3453AD00FCD54D /* MTRDiagnosticLogsDownloader.h */; }; BA09EB43247477BA00605257 /* libCHIP.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BA09EB3F2474762900605257 /* libCHIP.a */; }; + CF3B63CF2CA31E71003C1C87 /* MTROTAImageTransferHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF3B63CB2CA31E71003C1C87 /* MTROTAImageTransferHandler.h */; }; + CF3B63D02CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF3B63CC2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h */; }; + CF3B63D12CA31E71003C1C87 /* MTROTAImageTransferHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF3B63CD2CA31E71003C1C87 /* MTROTAImageTransferHandler.mm */; }; + CF3B63D22CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF3B63CE2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm */; }; D4288E872C8A273F002FEC53 /* MTRDevice_XPC_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = D4288E862C8A273F002FEC53 /* MTRDevice_XPC_Internal.h */; }; D444F9A72C6E8F9D007761E5 /* MTRXPCServerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D444F9A62C6E8F9D007761E5 /* MTRXPCServerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D444F9AA2C6E9A08007761E5 /* MTRXPCClientProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D444F9A82C6E99CA007761E5 /* MTRXPCClientProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -901,6 +905,10 @@ B4FCD56F2B603A6300832859 /* DownloadLogCommand.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DownloadLogCommand.mm; sourceTree = ""; }; BA09EB3F2474762900605257 /* libCHIP.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libCHIP.a; path = lib/libCHIP.a; sourceTree = BUILT_PRODUCTS_DIR; }; BA107AEE2470CFBB004287EB /* chip_xcode_build_connector.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = chip_xcode_build_connector.sh; sourceTree = ""; }; + CF3B63CB2CA31E71003C1C87 /* MTROTAImageTransferHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTROTAImageTransferHandler.h; sourceTree = ""; }; + CF3B63CC2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTROTAUnsolicitedBDXMessageHandler.h; sourceTree = ""; }; + CF3B63CD2CA31E71003C1C87 /* MTROTAImageTransferHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTROTAImageTransferHandler.mm; sourceTree = ""; }; + CF3B63CE2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MTROTAUnsolicitedBDXMessageHandler.mm; sourceTree = ""; }; D4288E862C8A273F002FEC53 /* MTRDevice_XPC_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDevice_XPC_Internal.h; sourceTree = ""; }; D437613E285BDC0D0051FEA2 /* MTRErrorTestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRErrorTestUtils.h; sourceTree = ""; }; D437613F285BDC0D0051FEA2 /* MTRTestKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRTestKeys.h; sourceTree = ""; }; @@ -1371,6 +1379,10 @@ B202528F2459E34F00F97062 /* CHIP */ = { isa = PBXGroup; children = ( + CF3B63CB2CA31E71003C1C87 /* MTROTAImageTransferHandler.h */, + CF3B63CD2CA31E71003C1C87 /* MTROTAImageTransferHandler.mm */, + CF3B63CC2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h */, + CF3B63CE2CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm */, D444F9A12C6E8058007761E5 /* XPC Protocol */, 88E07D602B9A89A4005FD53E /* MTRMetricKeys.h */, 88FA798B2B7B257100CD4B6F /* MTRMetricsCollector.h */, @@ -1835,6 +1847,7 @@ B2E0D7B2245B0B5C003C5B48 /* MTRManualSetupPayloadParser.h in Headers */, 5109E9C02CCAD64F0006884B /* MTRDeviceDataValidation.h in Headers */, 3CF134A7289D8ADA0017A19E /* MTRCSRInfo.h in Headers */, + CF3B63D02CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.h in Headers */, 88E07D612B9A89A4005FD53E /* MTRMetricKeys.h in Headers */, 3D4733B32BE2D1DA003DC19B /* MTRUtilities.h in Headers */, B2E0D7B1245B0B5C003C5B48 /* Matter.h in Headers */, @@ -1882,6 +1895,7 @@ 9B231B042C62EF650030EB37 /* (null) in Headers */, 515BE4ED2B72C0C5000BC1FD /* MTRUnfairLock.h in Headers */, 998F286F26D55EC5001846C6 /* MTRP256KeypairBridge.h in Headers */, + CF3B63CF2CA31E71003C1C87 /* MTROTAImageTransferHandler.h in Headers */, 2C222ADF255C811800E446B9 /* MTRBaseDevice_Internal.h in Headers */, 514C7A022B64223400DD6D7B /* MTRServerEndpoint_Internal.h in Headers */, 511913FC28C100EF009235E9 /* MTRBaseSubscriptionCallback.h in Headers */, @@ -2163,6 +2177,7 @@ 997DED162695343400975E97 /* MTRThreadOperationalDataset.mm in Sources */, 515C1C6F284F9FFB00A48F0C /* MTRFramework.mm in Sources */, 51029DF6293AA6100087AFB0 /* MTROperationalCertificateIssuer.mm in Sources */, + CF3B63D22CA31E71003C1C87 /* MTROTAUnsolicitedBDXMessageHandler.mm in Sources */, 27A53C1827FBC6920053F131 /* MTRAttestationTrustStoreBridge.mm in Sources */, 7592BCF62CBEE98C00EB74A0 /* CodegenDataModelProvider_Read.cpp in Sources */, 7592BCF72CBEE98C00EB74A0 /* Instance.cpp in Sources */, @@ -2202,6 +2217,7 @@ 1EC4CE5D25CC26E900D7304F /* MTRBaseClusters.mm in Sources */, 514C79F62B62F0B900DD6D7B /* util.cpp in Sources */, 51565CB22A7AD77600469F18 /* MTRDeviceControllerDataStore.mm in Sources */, + CF3B63D12CA31E71003C1C87 /* MTROTAImageTransferHandler.mm in Sources */, 51D0B12F2B617800006E3511 /* MTRAccessGrant.mm in Sources */, 88E6C9482B6334ED001A1FE0 /* MTRMetrics.mm in Sources */, 1ED276E226C5812A00547A89 /* MTRCluster.mm in Sources */, diff --git a/src/protocols/bdx/AsyncTransferFacilitator.cpp b/src/protocols/bdx/AsyncTransferFacilitator.cpp new file mode 100644 index 0000000000..2e3a0f0379 --- /dev/null +++ b/src/protocols/bdx/AsyncTransferFacilitator.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2024 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. + */ + +#include "AsyncTransferFacilitator.h" + +#include +#include + +namespace chip { +namespace bdx { + +AsyncTransferFacilitator::~AsyncTransferFacilitator() {} + +CHIP_ERROR AsyncTransferFacilitator::Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, + System::Clock::Timeout timeout) +{ + VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(exchangeCtx != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(!mExchange, CHIP_ERROR_INCORRECT_STATE); + + mSystemLayer = layer; + mExchange.Grab(exchangeCtx); + mTimeout = timeout; + mProcessingOutputEvents = false; + mDestroySelfAfterProcessingEvents = false; + return CHIP_NO_ERROR; +} + +/** + * Get events one by one from the TransferSession and process them, + * until there are no more events to process. + */ +void AsyncTransferFacilitator::ProcessOutputEvents() +{ + if (mProcessingOutputEvents) + { + ChipLogDetail(BDX, + "ProcessOutputEvents: we are already in the middle of processing events, so nothing to do here; when we " + "unwind to the processing loop the events will get processed."); + return; + } + + mProcessingOutputEvents = true; + + // Get the next output event and handle it based on the type of event. + // If its of type kMsgToSend send it over the exchange, otherwise call the HandleTransferSessionOutput + // virtual method that must be implemeted by the subclass of this class to handle the BDX message. + TransferSession::OutputEvent outEvent; + + mTransfer.GetNextAction(outEvent); + while (outEvent.EventType != TransferSession::OutputEventType::kNone) + { + if (outEvent.EventType == TransferSession::OutputEventType::kMsgToSend) + { + CHIP_ERROR err = SendMessage(outEvent.msgTypeData, outEvent.MsgData); + + // If we failed to send the message across the exchange, just abort the transfer. + // We have no way to notify our peer we are doing that (we can't send them a + // message!) but eventually they will time out. + if (err != CHIP_NO_ERROR) + { + DestroySelf(); + return; + } + + // If we send out a status report across the exchange, that means there was an error. + // We've sent our report about that error and can now abort the transfer. Our peer + // will respond to the status report by tearing down their side. + if (outEvent.msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) + { + mDestroySelfAfterProcessingEvents = true; + break; + } + } + else + { + HandleTransferSessionOutput(outEvent); + } + mTransfer.GetNextAction(outEvent); + } + + mProcessingOutputEvents = false; + + // If mDestroySelfAfterProcessingEvents is set (by our code above or by NotifyEventHandled), we need + // to call DestroySelf() after processing all pending output events. + if (mDestroySelfAfterProcessingEvents) + { + DestroySelf(); + } +} + +CHIP_ERROR AsyncTransferFacilitator::SendMessage(const TransferSession::MessageTypeData msgTypeData, + System::PacketBufferHandle & msgBuf) +{ + VerifyOrReturnError(mExchange, CHIP_ERROR_INCORRECT_STATE); + + Messaging::SendFlags sendFlags; + + // All messages that are sent expect a response, except for a StatusReport which would indicate an error and + // the end of the transfer. + if (!msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport)) + { + sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse); + } + + Messaging::ExchangeContext * ec = mExchange.Get(); + + // Set the response timeout on the exchange before sending the message. + ec->SetResponseTimeout(mTimeout); + return ec->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(msgBuf), sendFlags); +} + +CHIP_ERROR AsyncTransferFacilitator::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && payload) +{ + VerifyOrReturnError(mExchange, CHIP_ERROR_INCORRECT_STATE); + + VerifyOrReturnError(ec == mExchange.Get(), CHIP_ERROR_INCORRECT_STATE); + + CHIP_ERROR err = + mTransfer.HandleMessageReceived(payloadHeader, std::move(payload), System::SystemClock().GetMonotonicTimestamp()); + if (err != CHIP_NO_ERROR) + { + ChipLogError(BDX, "OnMessageReceived: Failed to handle message: %" CHIP_ERROR_FORMAT, err.Format()); + + // This should notify the transfer object to abort transfer so it can send a status report across the exchange + // when we call ProcessOutputEvents below. + mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err)); + } + else if (!payloadHeader.HasMessageType(MessageType::BlockAckEOF)) + { + // Almost every BDX message expect BlockAckEOF will follow up with a response on the exchange. + ec->WillSendMessage(); + } + + ProcessOutputEvents(); + return err; +} + +void AsyncTransferFacilitator::OnResponseTimeout(Messaging::ExchangeContext * ec) +{ + ChipLogDetail(BDX, "OnResponseTimeout, ec: " ChipLogFormatExchange, ChipLogValueExchange(ec)); + DestroySelf(); +} + +CHIP_ERROR AsyncResponder::Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, TransferRole role, + BitFlags xferControlOpts, uint16_t maxBlockSize, + System::Clock::Timeout timeout) +{ + ReturnErrorOnFailure(AsyncTransferFacilitator::Init(layer, exchangeCtx, timeout)); + ReturnErrorOnFailure(mTransfer.WaitForTransfer(role, xferControlOpts, maxBlockSize, timeout)); + return CHIP_NO_ERROR; +} + +void AsyncResponder::NotifyEventHandled(const TransferSession::OutputEventType eventType, CHIP_ERROR status) +{ + ChipLogDetail(BDX, "NotifyEventHandled : Event %s Error %" CHIP_ERROR_FORMAT, + TransferSession::OutputEvent::TypeToString(eventType), status.Format()); + + // If this is the end of the transfer (whether a clean end, or some sort of error condition), ensure that + // we destroy ourselves after processing any output events that might have been generated by + // the transfer session to handle end-of-transfer (e.g. in some error conditions it might want to send + // out a status report). + if (eventType == TransferSession::OutputEventType::kAckEOFReceived || + eventType == TransferSession::OutputEventType::kInternalError || + eventType == TransferSession::OutputEventType::kTransferTimeout || + eventType == TransferSession::OutputEventType::kStatusReceived) + { + mDestroySelfAfterProcessingEvents = true; + } + + // If there was an error handling the output event, this should notify the transfer object to abort transfer so it can send a + // status report across the exchange when we call ProcessOutputEvents below. + if (status != CHIP_NO_ERROR) + { + mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(status)); + } + + ProcessOutputEvents(); +} + +} // namespace bdx +} // namespace chip diff --git a/src/protocols/bdx/AsyncTransferFacilitator.h b/src/protocols/bdx/AsyncTransferFacilitator.h new file mode 100644 index 0000000000..1ad95d39e9 --- /dev/null +++ b/src/protocols/bdx/AsyncTransferFacilitator.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2024 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. + */ + +#include +#include +#include +#include +#include +#include + +#pragma once + +namespace chip { +namespace bdx { + +/** + * An abstract class with methods for receiving and sending BDX messages on an ExchangeContext. It interacts with the Transfer + * Session state machine to process the received messages and send any outgoing messages. + * Note: If the relevant fabric shuts down, it is the responsibility of the subclass that implements HandleTransferSessionOutput + * to destroy itself (and hence this object). + * + * This class does not define any methods for beginning a transfer or initializing the underlying TransferSession object. + * See AsyncResponder for a class that does. + * TODO: # 29334 - Add AsyncInitiator to handle the initiating side of a transfer. + * + * An AsyncTransferFacilitator is associated with a specific BDX transfer. + */ +class AsyncTransferFacilitator : public Messaging::ExchangeDelegate +{ +public: + AsyncTransferFacilitator() : mExchange(*this) {} + ~AsyncTransferFacilitator() override; + +protected: + CHIP_ERROR Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, System::Clock::Timeout timeout); + + // If subclasses override this method and they call the superclass's OnMessageReceived, the superclass + // may destroy the subclass's object before OnMessageReceived returns. + CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, + System::PacketBufferHandle && payload) override; + + // If subclasses override this method and they call the superclass's OnResponseTimeout, the superclass + // may destroy the subclass's object before OnResponseTimeout returns. + void OnResponseTimeout(Messaging::ExchangeContext * ec) override; + + /** + * This method should be implemented to contain business-logic handling of BDX messages + * and other TransferSession events. + * + * @param[in] event An OutputEvent that contains the output from the TransferSession object. + */ + virtual void HandleTransferSessionOutput(TransferSession::OutputEvent & event) = 0; + + /** + * This method should be implemented to destroy the object subclassing AsyncTransferFacilitator. + * + * This is a hook that is expected to be called by AsyncTransferFacilitator and allows subclasses + * to select an allocation strategy of their choice. + */ + virtual void DestroySelf() = 0; + + // Calling ProcessOutputEvents can destroy this object before the call returns. + void ProcessOutputEvents(); + + // The transfer session corresponding to this AsyncTransferFacilitator object. + TransferSession mTransfer; + + bool mDestroySelfAfterProcessingEvents = false; + +private: + bool mProcessingOutputEvents = false; + + // The Exchange holder that holds the exchange context used for sending and receiving BDX messages. + Messaging::ExchangeHolder mExchange; + + // The timeout for the BDX transfer session. + System::Clock::Timeout mTimeout; + + System::Layer * mSystemLayer; + + CHIP_ERROR SendMessage(const TransferSession::MessageTypeData msgTypeData, System::PacketBufferHandle & msgBuf); +}; + +/** + * An AsyncTransferFacilitator that is initialized to respond to an incoming BDX transfer request. + * An AsyncResponder object is associated with an exchange and handles all BDX messages sent over that exchange. + * + * Provides a method for initializing the TransferSession members but still needs to be extended to implement + * HandleTransferSessionOutput. + * + * An instance of some subclass of this class should be used as the exchange delegate for a BDX transfer. + */ +class AsyncResponder : public AsyncTransferFacilitator +{ +public: + /** + * Initialize the TransferSession state machine to be ready for an incoming transfer request. + * + * @param[in] exchangeCtx The exchange to use for the transfer. + * @param[in] role The role of the Responder: Sender or Receiver of BDX data + * @param[in] xferControlOpts Supported transfer modes (see TransferControlFlags) + * @param[in] maxBlockSize The maximum supported size of BDX Block data + * @param[in] timeout The chosen timeout delay for the BDX transfer + */ + CHIP_ERROR Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, TransferRole role, + BitFlags xferControlOpts, uint16_t maxBlockSize, System::Clock::Timeout timeout); + + /** + * Method that must be called by the subclass implementing HandleTransferSessionOutput to notify the AsyncResponder + * that it has handled the OutputEvent specified in "event" and "status" is the result of handling the event. + * + * Every call to HandleTransferSessionOutput must result in a call to NotifyEventHandled. The call + * to NotifyEventHandled may happen before HandleTransferSessionOutput returns, or may happen + * later, asynchronously. + + * Note: NotifyEventHandled is allowed to destroy the AsyncResponder before the call returns. + * Callers must be careful about this. + * + * @param[in] eventType The OutputEventType that was handled by the subclass. + * @param[in] status The error code that occured when handling the event if an error occurs. Otherwise CHIP_NO_ERROR. + */ + void NotifyEventHandled(const TransferSession::OutputEventType eventType, CHIP_ERROR status); +}; + +} // namespace bdx +} // namespace chip diff --git a/src/protocols/bdx/BUILD.gn b/src/protocols/bdx/BUILD.gn index a95fd02202..118410183f 100644 --- a/src/protocols/bdx/BUILD.gn +++ b/src/protocols/bdx/BUILD.gn @@ -18,6 +18,8 @@ static_library("bdx") { output_name = "libBdx" sources = [ + "AsyncTransferFacilitator.cpp", + "AsyncTransferFacilitator.h", "BdxMessages.cpp", "BdxMessages.h", "BdxTransferDiagnosticLog.cpp", diff --git a/src/protocols/bdx/BdxTransferSession.cpp b/src/protocols/bdx/BdxTransferSession.cpp index 89851493ba..fdf9bb2c84 100644 --- a/src/protocols/bdx/BdxTransferSession.cpp +++ b/src/protocols/bdx/BdxTransferSession.cpp @@ -916,6 +916,11 @@ bool TransferSession::IsTransferLengthDefinite() const } const char * TransferSession::OutputEvent::ToString(OutputEventType outputEventType) +{ + return TypeToString(outputEventType); +} + +const char * TransferSession::OutputEvent::TypeToString(OutputEventType outputEventType) { switch (outputEventType) { diff --git a/src/protocols/bdx/BdxTransferSession.h b/src/protocols/bdx/BdxTransferSession.h index 4a50e70fbb..ecfcac6680 100644 --- a/src/protocols/bdx/BdxTransferSession.h +++ b/src/protocols/bdx/BdxTransferSession.h @@ -136,6 +136,8 @@ class DLL_EXPORT TransferSession const char * ToString(OutputEventType outputEventType); + static const char * TypeToString(OutputEventType outputEventType); + static OutputEvent TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg); static OutputEvent TransferAcceptEvent(TransferAcceptData data); static OutputEvent TransferAcceptEvent(TransferAcceptData data, System::PacketBufferHandle msg); From 7d8c30bbbe6a1712e3a2e9b5a129818cbd71d199 Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Sat, 23 Nov 2024 07:44:07 +1300 Subject: [PATCH 079/219] Incremental improvements to controller dependencies (#36567) * Remove unused reference to CHIP_CONFIG_ENABLE_READ_CLIENT * ExamplePersistentStorage does not need CHIPDeviceController * Tidy up some Linux app-main dependencies * Reduce dependency of data model on controller * Fix log placerholders to use ChipLogFormatX64 in fabric sync example --- .../device_manager/DeviceManager.cpp | 20 +++--- examples/fabric-sync/admin/DeviceManager.cpp | 20 +++--- .../admin/DeviceSynchronization.cpp | 2 +- examples/fabric-sync/admin/FabricAdmin.cpp | 1 + examples/fabric-sync/main.cpp | 1 + .../fabric-sync/shell/AddBridgeCommand.cpp | 5 +- .../fabric-sync/shell/AddDeviceCommand.cpp | 5 +- .../fabric-sync/shell/PairDeviceCommand.cpp | 3 +- .../fabric-sync/shell/RemoveDeviceCommand.cpp | 2 +- examples/platform/linux/AppMain.cpp | 6 -- examples/platform/linux/AppMain.h | 18 ------ examples/platform/linux/BUILD.gn | 3 - .../linux/ControllerShellCommands.cpp | 8 ++- src/app/AttributePathParams.h | 4 +- src/app/chip_data_model.gni | 21 +++++-- .../content-app-observer.cpp | 3 +- .../content-control-server.cpp | 3 +- .../content-launch-server.cpp | 3 +- .../keypad-input-server.cpp | 3 +- .../media-playback-server.cpp | 3 +- .../target-navigator-server.cpp | 3 +- src/controller/BUILD.gn | 63 +++++++------------ src/controller/CHIPCluster.h | 3 +- src/controller/ExamplePersistentStorage.cpp | 2 +- src/controller/ExamplePersistentStorage.h | 8 ++- src/controller/ReadInteraction.h | 1 + src/controller/data_model/BUILD.gn | 1 - 27 files changed, 102 insertions(+), 113 deletions(-) diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 7e40a81965..41ee1f348a 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -227,8 +227,9 @@ void DeviceManager::SubscribeRemoteFabricBridge() if (error != CHIP_NO_ERROR) { - ChipLogError(NotSpecified, "Failed to subscribe to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + ChipLogError(NotSpecified, + "Failed to subscribe to the remote bridge (NodeId: " ChipLogFormatX64 "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } @@ -251,8 +252,9 @@ void DeviceManager::ReadSupportedDeviceCategories() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); } } @@ -293,8 +295,9 @@ void DeviceManager::RequestCommissioningApproval() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to request commissioning-approval to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to request commissioning-approval to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } @@ -417,8 +420,9 @@ void DeviceManager::SendCommissionNodeRequest(uint64_t requestId, uint16_t respo if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to send CommissionNode command to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to send CommissionNode command to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } diff --git a/examples/fabric-sync/admin/DeviceManager.cpp b/examples/fabric-sync/admin/DeviceManager.cpp index a632844195..f37ac4ac8f 100644 --- a/examples/fabric-sync/admin/DeviceManager.cpp +++ b/examples/fabric-sync/admin/DeviceManager.cpp @@ -221,8 +221,9 @@ void DeviceManager::SubscribeRemoteFabricBridge() if (error != CHIP_NO_ERROR) { - ChipLogError(NotSpecified, "Failed to subscribe to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + ChipLogError(NotSpecified, + "Failed to subscribe to the remote bridge (NodeId: " ChipLogFormatX64 "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } @@ -245,8 +246,9 @@ void DeviceManager::ReadSupportedDeviceCategories() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to read SupportedDeviceCategories from the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); } } @@ -287,8 +289,9 @@ void DeviceManager::RequestCommissioningApproval() if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to request commissioning-approval to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to request commissioning-approval to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } @@ -411,8 +414,9 @@ void DeviceManager::SendCommissionNodeRequest(uint64_t requestId, uint16_t respo if (error != CHIP_NO_ERROR) { ChipLogError(NotSpecified, - "Failed to send CommissionNode command to the remote bridge (NodeId: %lu). Error: %" CHIP_ERROR_FORMAT, - mRemoteBridgeNodeId, error.Format()); + "Failed to send CommissionNode command to the remote bridge (NodeId: " ChipLogFormatX64 + "). Error: %" CHIP_ERROR_FORMAT, + ChipLogValueX64(mRemoteBridgeNodeId), error.Format()); return; } } diff --git a/examples/fabric-sync/admin/DeviceSynchronization.cpp b/examples/fabric-sync/admin/DeviceSynchronization.cpp index 05a4fa9db8..527ccfa631 100644 --- a/examples/fabric-sync/admin/DeviceSynchronization.cpp +++ b/examples/fabric-sync/admin/DeviceSynchronization.cpp @@ -262,7 +262,7 @@ void DeviceSynchronizer::GetUniqueId() } else { - ChipLogDetail(NotSpecified, "Failed to get UniqueId from remote Fabric Sync Aggregator") + ChipLogDetail(NotSpecified, "Failed to get UniqueId from remote Fabric Sync Aggregator"); } } diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index de498cdb31..b4be20e0e2 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -17,6 +17,7 @@ #include "FabricAdmin.h" #include +#include #include #include diff --git a/examples/fabric-sync/main.cpp b/examples/fabric-sync/main.cpp index 8772400ff2..a372760d3a 100644 --- a/examples/fabric-sync/main.cpp +++ b/examples/fabric-sync/main.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include #include diff --git a/examples/fabric-sync/shell/AddBridgeCommand.cpp b/examples/fabric-sync/shell/AddBridgeCommand.cpp index 4ddebececd..eb8579c298 100644 --- a/examples/fabric-sync/shell/AddBridgeCommand.cpp +++ b/examples/fabric-sync/shell/AddBridgeCommand.cpp @@ -85,8 +85,9 @@ CHIP_ERROR AddBridgeCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - ChipLogProgress(NotSpecified, "Running AddBridgeCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mBridgeNodeId, - mSetupPINCode, mRemoteAddr, mRemotePort); + ChipLogProgress(NotSpecified, + "Running AddBridgeCommand with Node ID: " ChipLogFormatX64 ", PIN Code: %u, Address: %s, Port: %u", + ChipLogValueX64(mBridgeNodeId), mSetupPINCode, mRemoteAddr, mRemotePort); return admin::PairingManager::Instance().PairDevice(mBridgeNodeId, mSetupPINCode, mRemoteAddr, mRemotePort); } diff --git a/examples/fabric-sync/shell/AddDeviceCommand.cpp b/examples/fabric-sync/shell/AddDeviceCommand.cpp index f5098d2af7..47bcc22656 100644 --- a/examples/fabric-sync/shell/AddDeviceCommand.cpp +++ b/examples/fabric-sync/shell/AddDeviceCommand.cpp @@ -71,8 +71,9 @@ CHIP_ERROR AddDeviceCommand::RunCommand() return CHIP_ERROR_INVALID_ARGUMENT; } - ChipLogProgress(NotSpecified, "Running AddDeviceCommand with Node ID: %lu, PIN Code: %u, Address: %s, Port: %u", mNodeId, - mSetupPINCode, mRemoteAddr, mRemotePort); + ChipLogProgress(NotSpecified, + "Running AddDeviceCommand with Node ID: " ChipLogFormatX64 ", PIN Code: %u, Address: %s, Port: %u", + ChipLogValueX64(mNodeId), mSetupPINCode, mRemoteAddr, mRemotePort); admin::PairingManager::Instance().SetPairingDelegate(this); diff --git a/examples/fabric-sync/shell/PairDeviceCommand.cpp b/examples/fabric-sync/shell/PairDeviceCommand.cpp index 796c062a2d..bc06c80dfa 100644 --- a/examples/fabric-sync/shell/PairDeviceCommand.cpp +++ b/examples/fabric-sync/shell/PairDeviceCommand.cpp @@ -69,7 +69,8 @@ CHIP_ERROR PairDeviceCommand::RunCommand() return CHIP_ERROR_INVALID_ARGUMENT; } - ChipLogProgress(NotSpecified, "Running PairDeviceCommand with Node ID: %lu, Code: %s", mNodeId, mPayload); + ChipLogProgress(NotSpecified, "Running PairDeviceCommand with Node ID: " ChipLogFormatX64 ", Code: %s", + ChipLogValueX64(mNodeId), mPayload); admin::PairingManager::Instance().SetPairingDelegate(this); diff --git a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp index 649523c559..27c2f3e851 100644 --- a/examples/fabric-sync/shell/RemoveDeviceCommand.cpp +++ b/examples/fabric-sync/shell/RemoveDeviceCommand.cpp @@ -61,7 +61,7 @@ CHIP_ERROR RemoveDeviceCommand::RunCommand() admin::PairingManager::Instance().SetPairingDelegate(this); - ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: %lu", mNodeId); + ChipLogProgress(NotSpecified, "Running RemoveDeviceCommand with Node ID: " ChipLogFormatX64, ChipLogValueX64(mNodeId)); return admin::PairingManager::Instance().UnpairDevice(mNodeId); } diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index ddd4d82420..65763dc12d 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -33,8 +33,6 @@ #include #include -#include -#include #include #include @@ -51,10 +49,6 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include "CommissionerMain.h" #include -#include -#include -#include -#include #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #if defined(ENABLE_CHIP_SHELL) diff --git a/examples/platform/linux/AppMain.h b/examples/platform/linux/AppMain.h index 21ba04df7d..dc4a5d5be2 100644 --- a/examples/platform/linux/AppMain.h +++ b/examples/platform/linux/AppMain.h @@ -19,7 +19,6 @@ #pragma once #include -#include #include #include #include @@ -89,23 +88,6 @@ class DefaultAppMainLoopImplementation : public AppMainLoopImplementation */ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl = nullptr); -#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE - -using chip::PersistentStorageDelegate; -using chip::Controller::DeviceCommissioner; -using chip::Crypto::SessionKeystore; -using chip::Transport::PeerAddress; - -CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, PeerAddress address); -CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index); - -DeviceCommissioner * GetDeviceCommissioner(); -CommissionerDiscoveryController * GetCommissionerDiscoveryController(); -SessionKeystore * GetSessionKeystore(); -PersistentStorageDelegate * GetPersistentStorageDelegate(); - -#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE - // For extra init calls, the function will be called right before running Matter main loop. void ApplicationInit(); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 5b5d307e41..58536d5a23 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -96,8 +96,6 @@ source_set("app-main") { ":smco-test-event-trigger", ":water-heater-management-test-event-trigger", "${chip_root}/src/app/codegen-data-model-provider:instance-header", - "${chip_root}/src/controller:controller", - "${chip_root}/src/controller:gen_check_chip_controller_headers", "${chip_root}/src/lib", "${chip_root}/src/platform/logging:default", ] @@ -164,7 +162,6 @@ source_set("commissioner-main") { public_deps = [ "${chip_root}/src/controller:controller", - "${chip_root}/src/controller:gen_check_chip_controller_headers", "${chip_root}/src/lib", ] deps = [ "${chip_root}/src/app/server" ] diff --git a/examples/platform/linux/ControllerShellCommands.cpp b/examples/platform/linux/ControllerShellCommands.cpp index b2bc8af2d8..b33beedf3c 100644 --- a/examples/platform/linux/ControllerShellCommands.cpp +++ b/examples/platform/linux/ControllerShellCommands.cpp @@ -19,9 +19,9 @@ * @file Contains shell commands for for performing discovery (eg. of commissionable nodes) related to commissioning. */ -#include -#include -#include +#include "ControllerShellCommands.h" +#include "CommissionerMain.h" + #include #include #include @@ -33,6 +33,8 @@ #include #include +#include + namespace chip { namespace Shell { diff --git a/src/app/AttributePathParams.h b/src/app/AttributePathParams.h index dc3b71236d..52d5bb5972 100644 --- a/src/app/AttributePathParams.h +++ b/src/app/AttributePathParams.h @@ -25,9 +25,7 @@ namespace chip { namespace app { -#if CHIP_CONFIG_ENABLE_READ_CLIENT -class ReadClient; -#endif // CHIP_CONFIG_ENABLE_READ_CLIENT + struct AttributePathParams { AttributePathParams() = default; diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 3be8df5710..bd1950842a 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -235,6 +235,10 @@ template("chip_data_model") { deps = [] } + if (!defined(public_deps)) { + public_deps = [] + } + if (!defined(cflags)) { cflags = [] } @@ -269,9 +273,12 @@ template("chip_data_model") { } else if (cluster == "application-launcher-server") { sources += [ "${_app_root}/app-platform/ContentApp.cpp", + "${_app_root}/app-platform/ContentApp.h", "${_app_root}/app-platform/ContentAppPlatform.cpp", + "${_app_root}/app-platform/ContentAppPlatform.h", "${_app_root}/clusters/${cluster}/${cluster}.cpp", ] + deps += [ "${chip_root}/src/controller" ] } else if (cluster == "ota-requestor") { sources += [ # TODO - align name of folder ? @@ -288,6 +295,10 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/OTATestEventTriggerHandler.cpp", "${_app_root}/clusters/${cluster}/OTATestEventTriggerHandler.h", ] + + # TODO: DefaultOTARequestor depends on controller, however the cluster server itself does not. + # Maybe DefaultOTARequestor and related code should have its own source set. + deps += [ "${chip_root}/src/controller:interactions" ] } else if (cluster == "bindings") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", @@ -446,10 +457,6 @@ template("chip_data_model") { } } - if (!defined(public_deps)) { - public_deps = [] - } - public_deps += [ ":${_data_model_name}_codegen", ":${_data_model_name}_zapgen", @@ -459,12 +466,16 @@ template("chip_data_model") { "${chip_root}/src/app/common:attribute-type", "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/app/common:enums", + "${chip_root}/src/app/server", "${chip_root}/src/app/util:types", "${chip_root}/src/app/util/persistence", - "${chip_root}/src/controller", "${chip_root}/src/lib/core", "${chip_root}/src/lib/support", "${chip_root}/src/protocols/secure_channel", + + # TODO: Embedded example apps currently build with chip_build_controller = false, and so get a libCHIP without controller support, + # but nevertheless expect to have access to some of the "controller" code to implement bindings and related functionality. + "${chip_root}/src/controller:interactions", ] public_deps += codegen_data_model_PUBLIC_DEPS diff --git a/src/app/clusters/content-app-observer/content-app-observer.cpp b/src/app/clusters/content-app-observer/content-app-observer.cpp index d595b05812..ed726dd746 100644 --- a/src/app/clusters/content-app-observer/content-app-observer.cpp +++ b/src/app/clusters/content-app-observer/content-app-observer.cpp @@ -33,7 +33,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/content-control-server/content-control-server.cpp b/src/app/clusters/content-control-server/content-control-server.cpp index 8c9d076a71..944f7232d4 100644 --- a/src/app/clusters/content-control-server/content-control-server.cpp +++ b/src/app/clusters/content-control-server/content-control-server.cpp @@ -33,7 +33,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/content-launch-server/content-launch-server.cpp b/src/app/clusters/content-launch-server/content-launch-server.cpp index f0b5d5992e..a75565413d 100644 --- a/src/app/clusters/content-launch-server/content-launch-server.cpp +++ b/src/app/clusters/content-launch-server/content-launch-server.cpp @@ -29,7 +29,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #include diff --git a/src/app/clusters/keypad-input-server/keypad-input-server.cpp b/src/app/clusters/keypad-input-server/keypad-input-server.cpp index 6ca7a6dd46..8eab54017b 100644 --- a/src/app/clusters/keypad-input-server/keypad-input-server.cpp +++ b/src/app/clusters/keypad-input-server/keypad-input-server.cpp @@ -35,7 +35,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/media-playback-server/media-playback-server.cpp b/src/app/clusters/media-playback-server/media-playback-server.cpp index 5f762cf804..2a55f6372e 100644 --- a/src/app/clusters/media-playback-server/media-playback-server.cpp +++ b/src/app/clusters/media-playback-server/media-playback-server.cpp @@ -37,7 +37,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/app/clusters/target-navigator-server/target-navigator-server.cpp b/src/app/clusters/target-navigator-server/target-navigator-server.cpp index e42673a8bf..90985c14d0 100644 --- a/src/app/clusters/target-navigator-server/target-navigator-server.cpp +++ b/src/app/clusters/target-navigator-server/target-navigator-server.cpp @@ -36,7 +36,8 @@ #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -#include +#include // nogncheck + #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED using namespace chip; diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index b4e81158d4..1ddbeafaf1 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -24,32 +24,23 @@ source_set("nodatamodel") { public_deps = [ "${chip_root}/src/app" ] } -CHIP_CONTROLLER_HEADERS = [ "ExampleOperationalCredentialsIssuer.h" ] -CHIP_READ_CLIENT_HEADERS = [ - "CommissioningWindowOpener.h", - "CurrentFabricRemover.h", -] - -# This source set exists specifically to deny including them without dependencies -# if "controller" sources do not contain them -# -# They are NOT intended to be used directly. -# -# The intent for this is to force gn to be aware that these files are known and -# error out as `include not allowed due to missing dependency` even if -# controller is built without these sources -source_set("gen_check_chip_controller_headers") { - sources = CHIP_CONTROLLER_HEADERS -} - -source_set("gen_check_chip_read_client_headers") { - sources = CHIP_READ_CLIENT_HEADERS -} - source_set("delegates") { sources = [ "OperationalCredentialsDelegate.h" ] } +source_set("interactions") { + sources = [ + "CHIPCluster.h", + "CommandSenderAllocator.h", + "InvokeInteraction.h", + "ReadInteraction.h", + "TypedCommandCallback.h", + "TypedReadCallback.h", + "WriteInteraction.h", + ] + public_deps = [ "${chip_root}/src/app" ] +} + static_library("controller") { output_name = "libChipController" @@ -67,26 +58,23 @@ static_library("controller") { # dependencies "AbstractDnssdDiscoveryController.h", "AutoCommissioner.h", - "CHIPCluster.h", "CHIPCommissionableNodeController.h", "CHIPDeviceController.h", "CHIPDeviceControllerSystemState.h", - "CommandSenderAllocator.h", "CommissioneeDeviceProxy.h", "CommissioningDelegate.h", + "CommissioningWindowOpener.h", "CommissioningWindowParams.h", + "CurrentFabricRemover.h", "DeviceDiscoveryDelegate.h", "DevicePairingDelegate.h", - "InvokeInteraction.h", - "ReadInteraction.h", + "ExampleOperationalCredentialsIssuer.h", "SetUpCodePairer.h", - "TypedCommandCallback.h", - "TypedReadCallback.h", - "WriteInteraction.h", ] + deps = [ "${chip_root}/src/lib/address_resolve" ] + if (chip_controller && chip_build_controller) { - sources += CHIP_CONTROLLER_HEADERS sources += [ "AbstractDnssdDiscoveryController.cpp", "AutoCommissioner.cpp", @@ -100,8 +88,11 @@ static_library("controller") { "ExampleOperationalCredentialsIssuer.cpp", "SetUpCodePairer.cpp", ] + + # ExampleOperationalCredentialsIssuer uses TestGroupData + deps += [ "${chip_root}/src/lib/support:testing" ] + if (chip_enable_read_client) { - sources += CHIP_READ_CLIENT_HEADERS sources += [ "CHIPDeviceController.cpp", "CommissioningWindowOpener.cpp", @@ -110,9 +101,8 @@ static_library("controller") { } } - cflags = [ "-Wconversion" ] - public_deps = [ + ":interactions", "${chip_root}/src/app", "${chip_root}/src/app/server", "${chip_root}/src/lib/core", @@ -127,12 +117,7 @@ static_library("controller") { "${chip_root}/src/transport", ] - deps = [ "${chip_root}/src/lib/address_resolve" ] - - if (chip_controller && chip_build_controller) { - # ExampleOperationalCredentialsIssuer uses TestGroupData - deps += [ "${chip_root}/src/lib/support:testing" ] - } + cflags = [ "-Wconversion" ] public_configs = [ "${chip_root}/src:includes" ] } diff --git a/src/controller/CHIPCluster.h b/src/controller/CHIPCluster.h index c425b344c6..b3f35a9ac6 100644 --- a/src/controller/CHIPCluster.h +++ b/src/controller/CHIPCluster.h @@ -26,9 +26,8 @@ #pragma once -#include "app/ConcreteCommandPath.h" #include -#include +#include #include #include #include diff --git a/src/controller/ExamplePersistentStorage.cpp b/src/controller/ExamplePersistentStorage.cpp index 599f0980db..609b8ece98 100644 --- a/src/controller/ExamplePersistentStorage.cpp +++ b/src/controller/ExamplePersistentStorage.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -30,7 +31,6 @@ using Section = std::map; using Sections = std::map; using namespace ::chip; -using namespace ::chip::Controller; using namespace ::chip::IniEscaping; using namespace ::chip::Logging; diff --git a/src/controller/ExamplePersistentStorage.h b/src/controller/ExamplePersistentStorage.h index 685bcfdd4a..a82cdf9037 100644 --- a/src/controller/ExamplePersistentStorage.h +++ b/src/controller/ExamplePersistentStorage.h @@ -18,11 +18,13 @@ #pragma once -#include -#include -#include +#include +#include +#include #include +#include + class PersistentStorage : public chip::PersistentStorageDelegate { public: diff --git a/src/controller/ReadInteraction.h b/src/controller/ReadInteraction.h index 8eae6613dd..466e8eadbf 100644 --- a/src/controller/ReadInteraction.h +++ b/src/controller/ReadInteraction.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/src/controller/data_model/BUILD.gn b/src/controller/data_model/BUILD.gn index a0b57e7b91..a9a0ca370b 100644 --- a/src/controller/data_model/BUILD.gn +++ b/src/controller/data_model/BUILD.gn @@ -42,5 +42,4 @@ chip_codegen("cluster-tlv-metadata") { chip_data_model("data_model") { zap_file = "controller-clusters.zap" - allow_circular_includes_from = [ "${chip_root}/src/controller" ] } From b76c3fafa1b9f9d43480f110f461b1ce42180453 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 22 Nov 2024 10:56:24 -0800 Subject: [PATCH 080/219] [Fabric-Admin] Clean up pass through functions from Device Manager (#36614) * [Fabric-Admin] Clean up pass through functions from Device Manager * Restyled by clang-format --------- Co-authored-by: Restyled.io --- .../fabric-sync/FabricSyncCommand.cpp | 38 +++++++-------- .../device_manager/DeviceManager.cpp | 42 +---------------- .../device_manager/DeviceManager.h | 47 ------------------- examples/fabric-admin/rpc/RpcServer.cpp | 6 ++- 4 files changed, 24 insertions(+), 109 deletions(-) diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp index e8296fa478..59405786a8 100644 --- a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -32,6 +32,13 @@ using namespace ::chip; namespace admin { +namespace { + +constexpr uint32_t kDefaultSetupPinCode = 20202021; +constexpr uint16_t kDefaultLocalBridgePort = 5540; + +} // namespace + void FabricSyncAddBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) { if (mBridgeNodeId != deviceId) @@ -92,10 +99,8 @@ CHIP_ERROR FabricSyncAddBridgeCommand::RunCommand(NodeId remoteId) mBridgeNodeId = remoteId; - DeviceManager::Instance().PairRemoteFabricBridge(remoteId, mSetupPINCode, reinterpret_cast(mRemoteAddr.data()), - mRemotePort); - - return CHIP_NO_ERROR; + return PairingManager::Instance().PairDevice(remoteId, mSetupPINCode, reinterpret_cast(mRemoteAddr.data()), + mRemotePort); } void FabricSyncRemoveBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) @@ -135,9 +140,8 @@ CHIP_ERROR FabricSyncRemoveBridgeCommand::RunCommand() mBridgeNodeId = bridgeNodeId; PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().UnpairRemoteFabricBridge(); - return CHIP_NO_ERROR; + return PairingManager::Instance().UnpairDevice(bridgeNodeId); } void FabricSyncAddLocalBridgeCommand::OnCommissioningComplete(NodeId deviceId, CHIP_ERROR err) @@ -185,18 +189,10 @@ CHIP_ERROR FabricSyncAddLocalBridgeCommand::RunCommand(NodeId deviceId) PairingManager::Instance().SetPairingDelegate(this); mLocalBridgeNodeId = deviceId; - if (mSetupPINCode.HasValue()) - { - DeviceManager::Instance().SetLocalBridgeSetupPinCode(mSetupPINCode.Value()); - } - if (mLocalPort.HasValue()) - { - DeviceManager::Instance().SetLocalBridgePort(mLocalPort.Value()); - } + uint16_t localBridgePort = mLocalPort.ValueOr(kDefaultLocalBridgePort); + uint32_t localBridgeSetupPinCode = mSetupPINCode.ValueOr(kDefaultSetupPinCode); - DeviceManager::Instance().PairLocalFabricBridge(deviceId); - - return CHIP_NO_ERROR; + return PairingManager::Instance().PairDevice(deviceId, localBridgeSetupPinCode, "::1", localBridgePort); } void FabricSyncRemoveLocalBridgeCommand::OnDeviceRemoved(NodeId deviceId, CHIP_ERROR err) @@ -236,9 +232,8 @@ CHIP_ERROR FabricSyncRemoveLocalBridgeCommand::RunCommand() mLocalBridgeNodeId = bridgeNodeId; PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().UnpairLocalFabricBridge(); - return CHIP_NO_ERROR; + return PairingManager::Instance().UnpairDevice(mLocalBridgeNodeId); } void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ERROR err, SetupPayload payload) @@ -259,7 +254,10 @@ void FabricSyncDeviceCommand::OnCommissioningWindowOpened(NodeId deviceId, CHIP_ usleep(kCommissionPrepareTimeMs * 1000); - DeviceManager::Instance().PairRemoteDevice(nodeId, payloadBuffer); + if (PairingManager::Instance().PairDeviceWithCode(nodeId, payloadBuffer) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to sync device " ChipLogFormatX64, ChipLogValueX64(nodeId)); + } } else { diff --git a/examples/fabric-admin/device_manager/DeviceManager.cpp b/examples/fabric-admin/device_manager/DeviceManager.cpp index 41ee1f348a..67c634b440 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.cpp +++ b/examples/fabric-admin/device_manager/DeviceManager.cpp @@ -39,6 +39,7 @@ constexpr EndpointId kAggregatorEndpointId = 1; constexpr uint16_t kWindowTimeout = 300; constexpr uint16_t kIteration = 1000; constexpr uint16_t kMaxDiscriminatorLength = 4095; +constexpr uint16_t kResponseTimeoutSeconds = 30; } // namespace @@ -177,47 +178,6 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin } } -void DeviceManager::PairRemoteFabricBridge(NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, - uint16_t deviceRemotePort) -{ - if (PairingManager::Instance().PairDevice(nodeId, setupPINCode, deviceRemoteIp, deviceRemotePort) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair remote fabric bridge " ChipLogFormatX64, ChipLogValueX64(nodeId)); - } -} - -void DeviceManager::PairRemoteDevice(NodeId nodeId, const char * payload) -{ - if (PairingManager::Instance().PairDeviceWithCode(nodeId, payload) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair remote device " ChipLogFormatX64, ChipLogValueX64(nodeId)); - } -} - -void DeviceManager::PairLocalFabricBridge(NodeId nodeId) -{ - if (PairingManager::Instance().PairDevice(nodeId, mLocalBridgeSetupPinCode, "::1", mLocalBridgePort) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to pair local fabric bridge " ChipLogFormatX64, ChipLogValueX64(nodeId)); - } -} - -void DeviceManager::UnpairRemoteFabricBridge() -{ - if (PairingManager::Instance().UnpairDevice(mRemoteBridgeNodeId) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair remote bridge device " ChipLogFormatX64, ChipLogValueX64(mRemoteBridgeNodeId)); - } -} - -void DeviceManager::UnpairLocalFabricBridge() -{ - if (PairingManager::Instance().UnpairDevice(mLocalBridgeNodeId) != CHIP_NO_ERROR) - { - ChipLogError(NotSpecified, "Failed to unpair local bridge device " ChipLogFormatX64, ChipLogValueX64(mLocalBridgeNodeId)); - } -} - void DeviceManager::SubscribeRemoteFabricBridge() { ChipLogProgress(NotSpecified, "Start subscription to the remote bridge."); diff --git a/examples/fabric-admin/device_manager/DeviceManager.h b/examples/fabric-admin/device_manager/DeviceManager.h index 8c273ee53d..b326996bdd 100644 --- a/examples/fabric-admin/device_manager/DeviceManager.h +++ b/examples/fabric-admin/device_manager/DeviceManager.h @@ -28,10 +28,6 @@ namespace admin { -constexpr uint32_t kDefaultSetupPinCode = 20202021; -constexpr uint16_t kDefaultLocalBridgePort = 5540; -constexpr uint16_t kResponseTimeoutSeconds = 30; - class SyncedDevice { public: @@ -73,8 +69,6 @@ class DeviceManager void SetRemoteBridgeNodeId(chip::NodeId nodeId); - void SetLocalBridgePort(uint16_t port) { mLocalBridgePort = port; } - void SetLocalBridgeSetupPinCode(uint32_t pinCode) { mLocalBridgeSetupPinCode = pinCode; } void SetLocalBridgeNodeId(chip::NodeId nodeId) { mLocalBridgeNodeId = nodeId; } bool IsFabricSyncReady() const { return mRemoteBridgeNodeId != chip::kUndefinedNodeId; } @@ -133,45 +127,6 @@ class DeviceManager */ void OpenRemoteDeviceCommissioningWindow(chip::EndpointId remoteEndpointId); - /** - * @brief Pair a remote fabric bridge with a given node ID. - * - * This function initiates the pairing process for a remote fabric bridge using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param setupPINCode The setup PIN code used to authenticate the pairing process. - * @param deviceRemoteIp The IP address of the remote device that is being paired as part of the fabric bridge. - * @param deviceRemotePort The secured device port of the remote device that is being paired as part of the fabric bridge. - */ - void PairRemoteFabricBridge(chip::NodeId nodeId, uint32_t setupPINCode, const char * deviceRemoteIp, uint16_t deviceRemotePort); - - /** - * @brief Pair a remote Matter device to the current fabric. - * - * This function initiates the pairing process for a remote device using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - * @param payload The the QR code payload or a manual pairing code generated by the first commissioner - * instance when opened commissioning window. - */ - void PairRemoteDevice(chip::NodeId nodeId, const char * payload); - - /** - * @brief Pair a local fabric bridge with a given node ID. - * - * This function initiates the pairing process for the local fabric bridge using the specified parameters. - - * @param nodeId The user-defined ID for the node being commissioned. It doesn’t need to be the same ID, - * as for the first fabric. - */ - void PairLocalFabricBridge(chip::NodeId nodeId); - - void UnpairRemoteFabricBridge(); - - void UnpairLocalFabricBridge(); - void SubscribeRemoteFabricBridge(); void ReadSupportedDeviceCategories(); @@ -204,8 +159,6 @@ class DeviceManager // This represents the bridge on the other ecosystem. chip::NodeId mRemoteBridgeNodeId = chip::kUndefinedNodeId; - uint16_t mLocalBridgePort = kDefaultLocalBridgePort; - uint32_t mLocalBridgeSetupPinCode = kDefaultSetupPinCode; // The Node ID of the local bridge used for Fabric-Sync // This represents the bridge within its own ecosystem. chip::NodeId mLocalBridgeNodeId = chip::kUndefinedNodeId; diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index 06f7d8217c..a7c9259dde 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -179,7 +179,11 @@ class FabricAdmin final : public rpc::FabricAdmin, public admin::PairingDelegate // RequestCommissioningApproval, you need to wait for it to open a commissioning window on its bridge. usleep(kCommissionPrepareTimeMs * 1000); PairingManager::Instance().SetPairingDelegate(this); - DeviceManager::Instance().PairRemoteDevice(mNodeId, code.c_str()); + + if (PairingManager::Instance().PairDeviceWithCode(mNodeId, code.c_str()) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to commission device " ChipLogFormatX64, ChipLogValueX64(mNodeId)); + } } else { From 8c7acb66f1f47a66c078ab54286b4f4e2cdbe0af Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 22 Nov 2024 15:25:56 -0500 Subject: [PATCH 081/219] Set `dataModelProvider` as a required argument for `Controller::FactoryInitParams` (#36613) * Add dataModelProvider to Factor init parameters for the codegen data model provider * make setting the same data model on interaction model provider a noop * Fix compile * Fix links * Restyle * Restyled by prettier-markdown * Fix text * Fix some deps * Restyled by gn * Remove dependencies/auto-init of codegen data model in the interaction model. We now fully expect all applications to provide a data model provider * Fix include * Update src/app/InteractionModelEngine.cpp Co-authored-by: Boris Zbarsky * Address some code review comments * Fix unit tests * Restyle * Add more comments about why we have very intentional ordering --------- Co-authored-by: Andrei Litvin Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- docs/upgrading.md | 9 ++++--- .../chip-tool/commands/common/CHIPCommand.cpp | 2 ++ .../commands/common/CHIPCommand.cpp | 3 +++ examples/platform/linux/BUILD.gn | 5 +++- examples/platform/linux/CommissionerMain.cpp | 2 ++ src/app/BUILD.gn | 4 --- src/app/InteractionModelEngine.cpp | 23 ++++++++-------- src/app/InteractionModelEngine.h | 5 +--- ...bscriptionResumptionSessionEstablisher.cpp | 1 - src/app/tests/TestAclEvent.cpp | 2 ++ src/app/tests/TestInteractionModelEngine.cpp | 10 +++++++ .../CHIPDeviceControllerFactory.cpp | 26 +++++++++++++++++-- src/controller/CHIPDeviceControllerFactory.h | 5 ++++ .../java/AndroidDeviceControllerWrapper.cpp | 10 +++---- .../ChipDeviceController-ScriptBinding.cpp | 2 ++ .../python/chip/internal/CommissionerImpl.cpp | 2 ++ src/controller/tests/TestEventChunking.cpp | 3 +++ src/controller/tests/TestReadChunking.cpp | 5 ++++ src/controller/tests/TestWriteChunking.cpp | 14 +++++++--- .../CHIP/MTRDeviceControllerFactory.mm | 2 ++ 20 files changed, 98 insertions(+), 37 deletions(-) diff --git a/docs/upgrading.md b/docs/upgrading.md index de9ba38d23..517a83f657 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -93,11 +93,12 @@ Replacements for methods are: - `chip::app::GetAttributeAccessOverride` replaced by `chip::app::AttributeAccessInterfaceRegistry::Instance().Get` -### `ServerInitParams::dataModelProvider` in `Server::Init` +### `ServerInitParams::dataModelProvider` in `Server::Init` and `FactoryInitParams` -Server initialization requires a set data model provider to work rather than -auto-initializing ember-compatible code-generated data models. +Server and controller initialization require a set data model provider to work +rather than auto-initializing ember-compatible code-generated data models. To preserve `codegen/zap` generated logic, use `CodegenDataModelProviderInstance` (see changes in -). +[36558](https://github.com/project-chip/connectedhomeip/pull/36558) and +[36613](https://github.com/project-chip/connectedhomeip/pull/36613) ). diff --git a/examples/chip-tool/commands/common/CHIPCommand.cpp b/examples/chip-tool/commands/common/CHIPCommand.cpp index 4f14cb855e..ffa873b497 100644 --- a/examples/chip-tool/commands/common/CHIPCommand.cpp +++ b/examples/chip-tool/commands/common/CHIPCommand.cpp @@ -18,6 +18,7 @@ #include "CHIPCommand.h" +#include #include #include #include @@ -137,6 +138,7 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() factoryInitParams.opCertStore = &mOpCertStore; factoryInitParams.enableServerInteractions = NeedsOperationalAdvertising(); factoryInitParams.sessionKeystore = &sSessionKeystore; + factoryInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Init group data provider that will be used for all group keys and IPKs for the // chip-tool-configured fabrics. This is OK to do once since the fabric tables diff --git a/examples/fabric-admin/commands/common/CHIPCommand.cpp b/examples/fabric-admin/commands/common/CHIPCommand.cpp index e7f4071d12..1f761fcbbe 100644 --- a/examples/fabric-admin/commands/common/CHIPCommand.cpp +++ b/examples/fabric-admin/commands/common/CHIPCommand.cpp @@ -19,6 +19,8 @@ #include "CHIPCommand.h" #include "IcdManager.h" + +#include #include #include #include @@ -121,6 +123,7 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack() factoryInitParams.opCertStore = &mOpCertStore; factoryInitParams.enableServerInteractions = NeedsOperationalAdvertising(); factoryInitParams.sessionKeystore = &sSessionKeystore; + factoryInitParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Init group data provider that will be used for all group keys and IPKs for the // fabric-admin-configured fabrics. This is OK to do once since the fabric tables diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 58536d5a23..1d4f191cb8 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -164,7 +164,10 @@ source_set("commissioner-main") { "${chip_root}/src/controller:controller", "${chip_root}/src/lib", ] - deps = [ "${chip_root}/src/app/server" ] + deps = [ + "${chip_root}/src/app/codegen-data-model-provider:instance-header", + "${chip_root}/src/app/server", + ] if (chip_enable_transport_trace) { deps += [ "${chip_root}/examples/common/tracing:trace_handlers" ] diff --git a/examples/platform/linux/CommissionerMain.cpp b/examples/platform/linux/CommissionerMain.cpp index 300d2466bc..54ad104c01 100644 --- a/examples/platform/linux/CommissionerMain.cpp +++ b/examples/platform/linux/CommissionerMain.cpp @@ -24,6 +24,7 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include +#include #include #include #include @@ -134,6 +135,7 @@ CHIP_ERROR InitCommissioner(uint16_t commissionerPort, uint16_t udcListenPort, F factoryParams.fabricIndependentStorage = &gServerStorage; factoryParams.fabricTable = &Server::GetInstance().GetFabricTable(); factoryParams.sessionKeystore = &gSessionKeystore; + factoryParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); gGroupDataProvider.SetStorageDelegate(&gServerStorage); gGroupDataProvider.SetSessionKeystore(factoryParams.sessionKeystore); diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 26f9515bc1..2e017dd362 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -206,10 +206,6 @@ static_library("interaction-model") { "${chip_root}/src/app:global-attributes", ] - # Temporary dependency: codegen data provider instance should be provided - # by the application - deps += [ "${chip_root}/src/app/codegen-data-model-provider:instance-header" ] - public_deps = [ ":app_config", ":command-handler-impl", diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 0dd4df635b..9b76dd31bf 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -50,10 +50,6 @@ #include #include -// TODO: defaulting to codegen should eventually be an application choice and not -// hard-coded in the interaction model -#include - namespace chip { namespace app { namespace { @@ -1798,9 +1794,15 @@ Protocols::InteractionModel::Status InteractionModelEngine::CheckCommandExistenc DataModel::Provider * InteractionModelEngine::SetDataModelProvider(DataModel::Provider * model) { - // Alternting data model should not be done while IM is actively handling requests. + // Altering data model should not be done while IM is actively handling requests. VerifyOrDie(mReadHandlers.begin() == mReadHandlers.end()); + if (model == mDataModelProvider) + { + // no-op, just return + return model; + } + DataModel::Provider * oldModel = mDataModelProvider; if (oldModel != nullptr) { @@ -1830,14 +1832,11 @@ DataModel::Provider * InteractionModelEngine::SetDataModelProvider(DataModel::Pr return oldModel; } -DataModel::Provider * InteractionModelEngine::GetDataModelProvider() +DataModel::Provider * InteractionModelEngine::GetDataModelProvider() const { - if (mDataModelProvider == nullptr) - { - // These should be called within the CHIP processing loop. - assertChipStackLockedByCurrentThread(); - SetDataModelProvider(CodegenDataModelProviderInstance()); - } + // These should be called within the CHIP processing loop. + assertChipStackLockedByCurrentThread(); + return mDataModelProvider; } diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index ef4b041f19..3fa379129a 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -404,10 +404,7 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, } #endif - // Temporarily NOT const because the data model provider will be auto-set - // to codegen on first usage. This behaviour will be changed once each - // application must explicitly set the data model provider. - DataModel::Provider * GetDataModelProvider(); + DataModel::Provider * GetDataModelProvider() const; // MUST NOT be used while the interaction model engine is running as interaction // model functionality (e.g. active reads/writes/subscriptions) rely on data model diff --git a/src/app/SubscriptionResumptionSessionEstablisher.cpp b/src/app/SubscriptionResumptionSessionEstablisher.cpp index e6f1ba0217..f9ea25cb58 100644 --- a/src/app/SubscriptionResumptionSessionEstablisher.cpp +++ b/src/app/SubscriptionResumptionSessionEstablisher.cpp @@ -17,7 +17,6 @@ #include #include -#include namespace chip { namespace app { diff --git a/src/app/tests/TestAclEvent.cpp b/src/app/tests/TestAclEvent.cpp index bbded46298..13b3e36491 100644 --- a/src/app/tests/TestAclEvent.cpp +++ b/src/app/tests/TestAclEvent.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -217,6 +218,7 @@ TEST_F(TestAclEvent, TestReadRoundtripWithEventStatusIBInEventReport) auto * engine = chip::app::InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); // A custom AccessControl::Delegate has been installed that grants privilege to any cluster except the test cluster. diff --git a/src/app/tests/TestInteractionModelEngine.cpp b/src/app/tests/TestInteractionModelEngine.cpp index 0a4a8bd5af..acc19c12f4 100644 --- a/src/app/tests/TestInteractionModelEngine.cpp +++ b/src/app/tests/TestInteractionModelEngine.cpp @@ -88,6 +88,7 @@ TEST_F(TestInteractionModelEngine, TestAttributePathParamsPushRelease) InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); SingleLinkedListNode * attributePathParamsList = nullptr; @@ -123,6 +124,7 @@ TEST_F(TestInteractionModelEngine, TestRemoveDuplicateConcreteAttribute) InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler())); SingleLinkedListNode * attributePathParamsList = nullptr; @@ -259,6 +261,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx1); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that there are no active subscriptions @@ -306,6 +309,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx1); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that both Alice and Bob have no active subscriptions @@ -364,6 +368,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx2); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that both Alice and Bob have no active subscriptions @@ -446,6 +451,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription ASSERT_TRUE(exchangeCtx22); // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Verify that both Alice and Bob have no active subscriptions @@ -525,6 +531,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubjectHasActiveSubscription FabricIndex bobFabricIndex = 1; // InteractionModelEngine init + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); // Make sure we are using CASE sessions, because there is no defunct-marking for PASE. @@ -575,6 +582,7 @@ TEST_F(TestInteractionModelEngine, TestSubjectHasPersistedSubscription) EXPECT_EQ(subscriptionStorage.Init(&storage), CHIP_NO_ERROR); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler(), nullptr, &subscriptionStorage)); @@ -630,6 +638,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestSubscriptionResumptionTimer) InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); uint32_t timeTillNextResubscriptionMs; @@ -661,6 +670,7 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestDecrementNumSubscriptionsToR constexpr uint8_t kNumberOfSubsToResume = 5; uint8_t numberOfSubsRemaining = kNumberOfSubsToResume; + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); EXPECT_EQ(engine->Init(&GetExchangeManager(), &GetFabricTable(), app::reporting::GetDefaultReportScheduler()), CHIP_NO_ERROR); #if CHIP_CONFIG_ENABLE_ICD_CIP && !CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp index e7e718964d..a5fe94dcd4 100644 --- a/src/controller/CHIPDeviceControllerFactory.cpp +++ b/src/controller/CHIPDeviceControllerFactory.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -100,6 +101,10 @@ CHIP_ERROR DeviceControllerFactory::ReinitSystemStateIfNecessary() params.certificateValidityPolicy = mCertificateValidityPolicy; params.sessionResumptionStorage = mSessionResumptionStorage; + // re-initialization keeps any previously initialized values. The only place where + // a provider exists is in the InteractionModelEngine, so just say "keep it as is". + params.dataModelProvider = app::InteractionModelEngine::GetInstance()->GetDataModelProvider(); + return InitSystemState(params); } @@ -127,6 +132,13 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) ChipLogError(Controller, "Warning: Device Controller Factory should be with a CHIP Device Layer..."); #endif // CONFIG_DEVICE_LAYER + if (params.dataModelProvider == nullptr) + { + ChipLogError(AppServer, "Device Controller Factory requires a `dataModelProvider` value."); + ChipLogError(AppServer, "For backwards compatibility, you likely can use `CodegenDataModelProviderInstance()`"); + } + + VerifyOrReturnError(params.dataModelProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(stateParams.systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(stateParams.udpEndPointManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -238,6 +250,16 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) ReturnErrorOnFailure(stateParams.unsolicitedStatusHandler->Init(stateParams.exchangeMgr)); ReturnErrorOnFailure(stateParams.bdxTransferServer->Init(stateParams.systemLayer, stateParams.exchangeMgr)); + chip::app::InteractionModelEngine * interactionModelEngine = chip::app::InteractionModelEngine::GetInstance(); + + // Note placement of this BEFORE `InitDataModelHandler` since InitDataModelHandler may + // rely on ember (does emberAfInit() and configure which may load data from NVM). + // + // Expected forward path is that we will move move and more things inside datamodel + // provider (e.g. storage settings) so we want datamodelprovider available before + // `InitDataModelHandler`. + interactionModelEngine->SetDataModelProvider(params.dataModelProvider); + InitDataModelHandler(); ReturnErrorOnFailure(Dnssd::Resolver::Instance().Init(stateParams.udpEndPointManager)); @@ -295,8 +317,8 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) stateParams.caseSessionManager = Platform::New(); ReturnErrorOnFailure(stateParams.caseSessionManager->Init(stateParams.systemLayer, sessionManagerConfig)); - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init( - stateParams.exchangeMgr, stateParams.fabricTable, stateParams.reportScheduler, stateParams.caseSessionManager)); + ReturnErrorOnFailure(interactionModelEngine->Init(stateParams.exchangeMgr, stateParams.fabricTable, stateParams.reportScheduler, + stateParams.caseSessionManager)); // store the system state mSystemState = chip::Platform::New(std::move(stateParams)); diff --git a/src/controller/CHIPDeviceControllerFactory.h b/src/controller/CHIPDeviceControllerFactory.h index 16e2ad4871..0efe451833 100644 --- a/src/controller/CHIPDeviceControllerFactory.h +++ b/src/controller/CHIPDeviceControllerFactory.h @@ -160,6 +160,11 @@ struct FactoryInitParams /* The port used for operational communication to listen for and send messages over UDP/TCP. * The default value of `0` will pick any available port. */ uint16_t listenPort = 0; + + // MUST NOT be null during initialization: every application must define the + // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance` + // for ember/zap-generated models. + chip::app::DataModel::Provider * dataModelProvider = nullptr; }; class DeviceControllerFactory diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 3eb6dd82e4..2582e8f0e7 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -25,17 +25,16 @@ #include +#include #include - -#include -#include -#include - #include #include #include #include #include +#include +#include +#include #include #include #include @@ -210,6 +209,7 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew( setupParams.defaultCommissioner = &wrapper->mAutoCommissioner; initParams.fabricIndependentStorage = wrapperStorage; initParams.sessionKeystore = &wrapper->mSessionKeystore; + initParams.dataModelProvider = app::CodegenDataModelProviderInstance(); wrapper->mGroupDataProvider.SetStorageDelegate(wrapperStorage); wrapper->mGroupDataProvider.SetSessionKeystore(initParams.sessionKeystore); diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 11fdf763da..b5dab55f84 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -271,6 +272,7 @@ PyChipError pychip_DeviceController_StackInit(Controller::Python::StorageAdapter factoryParams.fabricIndependentStorage = storageAdapter; factoryParams.sessionKeystore = &sSessionKeystore; + factoryParams.dataModelProvider = app::CodegenDataModelProviderInstance(); sICDClientStorage.Init(storageAdapter, &sSessionKeystore); diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index 7092024267..31824508d9 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -135,6 +136,7 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N factoryParams.fabricIndependentStorage = &gServerStorage; factoryParams.sessionKeystore = &gSessionKeystore; + factoryParams.dataModelProvider = chip::app::CodegenDataModelProviderInstance(); // Initialize group data provider for local group key state and IPKs gGroupDataProvider.SetStorageDelegate(&gServerStorage); diff --git a/src/controller/tests/TestEventChunking.cpp b/src/controller/tests/TestEventChunking.cpp index d0f4999ee7..17e8ece034 100644 --- a/src/controller/tests/TestEventChunking.cpp +++ b/src/controller/tests/TestEventChunking.cpp @@ -288,6 +288,7 @@ TEST_F(TestEventChunking, TestEventChunking) // Initialize the ember side server logic CodegenDataModelProviderInstance()->Shutdown(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -355,6 +356,7 @@ TEST_F(TestEventChunking, TestMixedEventsAndAttributesChunking) // Initialize the ember side server logic CodegenDataModelProviderInstance()->Shutdown(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -432,6 +434,7 @@ TEST_F(TestEventChunking, TestMixedEventsAndLargeAttributesChunking) // Initialize the ember side server logic CodegenDataModelProviderInstance()->Shutdown(); + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. diff --git a/src/controller/tests/TestReadChunking.cpp b/src/controller/tests/TestReadChunking.cpp index 989d910052..8614b6acf4 100644 --- a/src/controller/tests/TestReadChunking.cpp +++ b/src/controller/tests/TestReadChunking.cpp @@ -25,6 +25,7 @@ #include "app-common/zap-generated/ids/Attributes.h" #include "app-common/zap-generated/ids/Clusters.h" #include "app/ConcreteAttributePath.h" +#include "app/codegen-data-model-provider/Instance.h" #include "protocols/interaction_model/Constants.h" #include #include @@ -481,6 +482,7 @@ TEST_F(TestReadChunking, TestChunking) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -543,6 +545,7 @@ TEST_F(TestReadChunking, TestListChunking) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -644,6 +647,7 @@ TEST_F(TestReadChunking, TestBadChunking) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetWriterReserved(0); @@ -695,6 +699,7 @@ TEST_F(TestReadChunking, TestDynamicEndpoint) app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance(); // Initialize the ember side server logic + engine->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. diff --git a/src/controller/tests/TestWriteChunking.cpp b/src/controller/tests/TestWriteChunking.cpp index 4efc098186..f2f5a0822b 100644 --- a/src/controller/tests/TestWriteChunking.cpp +++ b/src/controller/tests/TestWriteChunking.cpp @@ -21,16 +21,16 @@ #include -#include "app-common/zap-generated/ids/Attributes.h" -#include "app-common/zap-generated/ids/Clusters.h" -#include "app/ConcreteAttributePath.h" -#include "protocols/interaction_model/Constants.h" #include +#include +#include #include #include #include +#include #include #include +#include #include #include #include @@ -39,6 +39,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -211,6 +212,7 @@ TEST_F(TestWriteChunking, TestListChunking) auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -284,6 +286,7 @@ TEST_F(TestWriteChunking, TestBadChunking) bool atLeastOneRequestFailed = false; // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -363,6 +366,7 @@ TEST_F(TestWriteChunking, TestConflictWrite) auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -437,6 +441,7 @@ TEST_F(TestWriteChunking, TestNonConflictWrite) auto sessionHandle = GetSessionBobToAlice(); // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. @@ -585,6 +590,7 @@ void TestWriteChunking::RunTest(Instructions instructions) TEST_F(TestWriteChunking, TestTransactionalList) { // Initialize the ember side server logic + app::InteractionModelEngine::GetInstance()->SetDataModelProvider(CodegenDataModelProviderInstance()); InitDataModelHandler(); // Register our fake dynamic endpoint. diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index ce208690b1..4eb7328949 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -50,6 +50,7 @@ #import +#include #include #include #include @@ -398,6 +399,7 @@ - (BOOL)_startControllerFactory:(MTRDeviceControllerFactoryParams *)startupParam params.opCertStore = _opCertStore; params.certificateValidityPolicy = &_certificateValidityPolicy; params.sessionResumptionStorage = _sessionResumptionStorage; + params.dataModelProvider = app::CodegenDataModelProviderInstance(); SuccessOrExit(err = _controllerFactory->Init(params)); } From 099d1733cd0e25644f55ff4859e5b16128df0e1c Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 22 Nov 2024 15:33:15 -0500 Subject: [PATCH 082/219] Mark _deviceForNodeID:createIfNeeded: as possibly returning nil. (#36617) --- src/darwin/Framework/CHIP/MTRDeviceController.mm | 2 +- src/darwin/Framework/CHIP/MTRDeviceController_Internal.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 8bbad10886..3b222a1e3e 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -371,7 +371,7 @@ - (MTRDevice *)_setupDeviceForNodeID:(NSNumber *)nodeID prefetchedClusterData:(N return [[MTRDevice alloc] initForSubclassesWithNodeID:nodeID controller:self]; } -- (MTRDevice *)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded +- (MTRDevice * _Nullable)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded { std::lock_guard lock(*self.deviceMapLock); MTRDevice * deviceToReturn = [_nodeIDToDeviceMap objectForKey:nodeID]; diff --git a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h index ed5e870adc..0ca85b1f22 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h +++ b/src/darwin/Framework/CHIP/MTRDeviceController_Internal.h @@ -107,7 +107,8 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Device-specific data and SDK access // DeviceController will act as a central repository for this opaque dictionary that MTRDevice manages - (MTRDevice *)deviceForNodeID:(NSNumber *)nodeID; -- (MTRDevice *)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded; +// _deviceForNodeID:createIfNeeded: can only return nil if NO is passed for createIfNeeded. +- (MTRDevice * _Nullable)_deviceForNodeID:(NSNumber *)nodeID createIfNeeded:(BOOL)createIfNeeded; /** * _setupDeviceForNodeID is a hook expected to be implemented by subclasses to * actually allocate a device object of the right type. From 9d604895004095da9d09bb62a78e5c4e8914637a Mon Sep 17 00:00:00 2001 From: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> Date: Fri, 22 Nov 2024 17:01:16 -0500 Subject: [PATCH 083/219] Add some constraint checks to the colorcontrol cluster commands (#36542) * add some constraint checks to the colorcontrol cluster commands * Update src/app/clusters/color-control-server/color-control-server.cpp Co-authored-by: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> * Addrese comments. Move ConstraintCheck Before Unsupported command checks. Add contraint checks for ColorTemperatureMireds arguments * Update src/app/clusters/color-control-server/color-control-server.cpp Co-authored-by: Boris Zbarsky --------- Co-authored-by: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Co-authored-by: Boris Zbarsky --- .../color-control-server.cpp | 79 ++++++++++++++++--- .../color-control-server.h | 3 + 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/app/clusters/color-control-server/color-control-server.cpp b/src/app/clusters/color-control-server/color-control-server.cpp index a01de7fad2..98379b26a7 100644 --- a/src/app/clusters/color-control-server/color-control-server.cpp +++ b/src/app/clusters/color-control-server/color-control-server.cpp @@ -1264,10 +1264,13 @@ EmberEventControl * ColorControlServer::configureHSVEventControl(EndpointId endp * @param saturation Target saturation * @param transitionTime Transition time in 10th of seconds * @return Status::Success When successful, - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state, + * Status::ConstraintError if the saturation or tansitionTime are above maximum. */ Status ColorControlServer::moveToSaturation(EndpointId endpoint, uint8_t saturation, uint16_t transitionTime) { + VerifyOrReturnError(saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnError(transitionTime <= kMaxTransitionTime, Status::ConstraintError); Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionState(endpoint); VerifyOrReturnError(nullptr != colorSaturationTransitionState, Status::UnsupportedEndpoint); @@ -1307,6 +1310,7 @@ Status ColorControlServer::moveToSaturation(EndpointId endpoint, uint8_t saturat * was called by MoveHue command and rate is a uint8 value. * @return Status::Success When successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state, + * Status::ConstraintError if the hue, saturation or transitionTime, are above maximum. */ Status ColorControlServer::moveToHueAndSaturation(EndpointId endpoint, uint16_t hue, uint8_t saturation, uint16_t transitionTime, bool isEnhanced) @@ -1315,6 +1319,10 @@ Status ColorControlServer::moveToHueAndSaturation(EndpointId endpoint, uint16_t uint16_t halfWay = isEnhanced ? HALF_MAX_UINT16T : HALF_MAX_UINT8T; bool moveUp; + VerifyOrReturnError((isEnhanced || hue <= MAX_HUE_VALUE), Status::ConstraintError); + VerifyOrReturnError(saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnError(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + uint16_t epIndex = getEndpointIndex(endpoint); Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionStateByIndex(epIndex); ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionStateByIndex(epIndex); @@ -1502,10 +1510,11 @@ Status ColorControlServer::moveToHueCommand(EndpointId endpoint, uint16_t hue, D bool isEnhanced) { MATTER_TRACE_SCOPE("moveToHue", "ColorControl"); - VerifyOrReturnValue(moveDirection != DirectionEnum::kUnknownEnumValue, Status::InvalidCommand); - // Command Parameters constraint checks: VerifyOrReturnValue((isEnhanced || hue <= MAX_HUE_VALUE), Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + + VerifyOrReturnValue(moveDirection != DirectionEnum::kUnknownEnumValue, Status::InvalidCommand); ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); VerifyOrReturnValue(colorHueTransitionState != nullptr, Status::UnsupportedEndpoint); @@ -1612,7 +1621,6 @@ Status ColorControlServer::moveToHueCommand(EndpointId endpoint, uint16_t hue, D * was called by MoveHue command and rate is a uint8 value. * @return Status::Success when successful, * Status::ConstraintError when the other parameters are outside their defined value range. - */ Status ColorControlServer::moveToHueAndSaturationCommand(EndpointId endpoint, uint16_t hue, uint8_t saturation, uint16_t transitionTime, BitMask optionsMask, @@ -1622,6 +1630,7 @@ Status ColorControlServer::moveToHueAndSaturationCommand(EndpointId endpoint, ui // Command Parameters constraint checks: VerifyOrReturnValue((isEnhanced || hue <= MAX_HUE_VALUE), Status::ConstraintError); VerifyOrReturnValue(saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); VerifyOrReturnValue(shouldExecuteIfOff(endpoint, optionsMask, optionsOverride), Status::Success); @@ -1646,12 +1655,19 @@ Status ColorControlServer::moveToHueAndSaturationCommand(EndpointId endpoint, ui * @return Status::Success when successful, * Status::InvalidCommand when StepSize is 0 or an unknown HueStepMode is provided * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a hue transition state. + * Status::ConstraintError when the other parameters are outside their defined value range. */ Status ColorControlServer::stepHueCommand(EndpointId endpoint, HueStepMode stepMode, uint16_t stepSize, uint16_t transitionTime, BitMask optionsMask, BitMask optionsOverride, bool isEnhanced) { MATTER_TRACE_SCOPE("stepHue", "ColorControl"); + // Command Parameters constraint checks: + // The non-enhanced variant passed a uint8 type for transitionTime and the full range (0-255) is allowed + if (isEnhanced) + { + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + } // Confirm validity of the step mode and step size received VerifyOrReturnValue(stepMode != HueStepMode::kUnknownEnumValue, Status::InvalidCommand); VerifyOrReturnValue(stepSize != 0, Status::InvalidCommand); @@ -1787,7 +1803,8 @@ Status ColorControlServer::moveSaturationCommand(EndpointId endpoint, const Comm * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state (verified in - * moveToSaturation function) Status::ConstraintError when a command parameters is outside its defined value range. + * moveToSaturation function) + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToSaturationCommand(EndpointId endpoint, const Commands::MoveToSaturation::DecodableType & commandData) @@ -1795,6 +1812,7 @@ Status ColorControlServer::moveToSaturationCommand(EndpointId endpoint, MATTER_TRACE_SCOPE("moveToSaturation", "ColorControl"); // Command Parameters constraint checks: VerifyOrReturnValue(commandData.saturation <= MAX_SATURATION_VALUE, Status::ConstraintError); + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); VerifyOrReturnValue(shouldExecuteIfOff(endpoint, commandData.optionsMask, commandData.optionsOverride), Status::Success); Status status = moveToSaturation(endpoint, commandData.saturation, commandData.transitionTime); @@ -1810,7 +1828,7 @@ Status ColorControlServer::moveToSaturationCommand(EndpointId endpoint, * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::InvalidCommand when a step size of 0 or an unknown SaturationStepMode is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a saturation transition state, */ Status ColorControlServer::stepSaturationCommand(EndpointId endpoint, const Commands::StepSaturation::DecodableType & commandData) { @@ -1861,7 +1879,7 @@ Status ColorControlServer::stepSaturationCommand(EndpointId endpoint, const Comm * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::InvalidCommand when an unknown action or direction is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a hue transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a hue transition state, */ Status ColorControlServer::colorLoopCommand(EndpointId endpoint, const Commands::ColorLoopSet::DecodableType & commandData) { @@ -2146,10 +2164,18 @@ EmberEventControl * ColorControlServer::configureXYEventControl(EndpointId endpo * @param colorX target X * @param colorY target Y * @param transitionTime transition time in 10th of seconds - * @return Status::Success if successful,Status::UnsupportedEndpoint XY is not supported on the endpoint + * @return Status::Success if successful, + * @return Status::Success when successful, + * Status::UnsupportedEndpoint XY is not supported on the endpoint, + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToColor(EndpointId endpoint, uint16_t colorX, uint16_t colorY, uint16_t transitionTime) { + // Command Parameters constraint checks: + VerifyOrReturnValue(colorX <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(colorY <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + uint16_t epIndex = getEndpointIndex(endpoint); Color16uTransitionState * colorXTransitionState = getXTransitionStateByIndex(epIndex); Color16uTransitionState * colorYTransitionState = getYTransitionStateByIndex(epIndex); @@ -2201,9 +2227,15 @@ Status ColorControlServer::moveToColor(EndpointId endpoint, uint16_t colorX, uin * @return Status::Success when successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a Color XY transition state (verified in * moveToColor function), + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToColorCommand(EndpointId endpoint, const Commands::MoveToColor::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.colorX <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorY <= MAX_CIE_XY_VALUE, Status::ConstraintError); + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(shouldExecuteIfOff(endpoint, commandData.optionsMask, commandData.optionsOverride), Status::Success); Status status = moveToColor(endpoint, commandData.colorX, commandData.colorY, commandData.transitionTime); @@ -2302,10 +2334,14 @@ Status ColorControlServer::moveColorCommand(EndpointId endpoint, const Commands: * @param commandData Struct containing the parameters of the command * @return Status::Success when successful, * Status::InvalidCommand when a step X and Y of 0 is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a Color XY transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a Color XY transition state, + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::stepColorCommand(EndpointId endpoint, const Commands::StepColor::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(commandData.stepX != 0 || commandData.stepY != 0, Status::InvalidCommand); uint16_t epIndex = getEndpointIndex(endpoint); @@ -2440,8 +2476,11 @@ ColorControlServer::Color16uTransitionState * ColorControlServer::getTempTransit */ Status ColorControlServer::moveToColorTemp(EndpointId aEndpoint, uint16_t colorTemperature, uint16_t transitionTime) { - EndpointId endpoint = aEndpoint; + // Command Parameters constraint checks: + VerifyOrReturnValue(colorTemperature <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(transitionTime <= kMaxTransitionTime, Status::ConstraintError); + EndpointId endpoint = aEndpoint; Color16uTransitionState * colorTempTransitionState = getTempTransitionState(endpoint); VerifyOrReturnError(nullptr != colorTempTransitionState, Status::UnsupportedEndpoint); @@ -2638,10 +2677,15 @@ void ColorControlServer::updateTempCommand(EndpointId endpoint) * @return Status::Success when successful, * Status::InvalidCommand when a rate of 0 for a non-stop move or an unknown HueMoveMode is provided * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color temp transition state. + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveColorTempCommand(EndpointId endpoint, const Commands::MoveColorTemperature::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.colorTemperatureMinimumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorTemperatureMaximumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + // check moveMode and rate before any operation is done on the transition states // rate value is ignored if the MoveMode is stop VerifyOrReturnValue(commandData.moveMode != HueMoveMode::kUnknownEnumValue, Status::InvalidCommand); @@ -2734,11 +2778,16 @@ Status ColorControlServer::moveColorTempCommand(EndpointId endpoint, * @param commandData Struct containing the parameters of the command. * @return Status::Success when successful, * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color XY transition state (verified in - * moveToColorTemp function). + * moveToColorTemp function), + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::moveToColorTempCommand(EndpointId endpoint, const Commands::MoveToColorTemperature::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.colorTemperatureMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(shouldExecuteIfOff(endpoint, commandData.optionsMask, commandData.optionsOverride), Status::Success); Status status = moveToColorTemp(endpoint, commandData.colorTemperatureMireds, commandData.transitionTime); @@ -2754,11 +2803,17 @@ Status ColorControlServer::moveToColorTempCommand(EndpointId endpoint, * @param commandData Struct containing the parameters of the command * @return Status::Success when successful, * Status::InvalidCommand when stepSize is 0 or an unknown stepMode is provided - * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color temp transition state. + * Status::UnsupportedEndpoint when the provided endpoint doesn't correspond with a color temp transition state, + * Status::ConstraintError when a command parameter is outside its defined value range. */ Status ColorControlServer::stepColorTempCommand(EndpointId endpoint, const Commands::StepColorTemperature::DecodableType & commandData) { + // Command Parameters constraint checks: + VerifyOrReturnValue(commandData.transitionTime <= kMaxTransitionTime, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorTemperatureMinimumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + VerifyOrReturnValue(commandData.colorTemperatureMaximumMireds <= kMaxColorTemperatureMireds, Status::ConstraintError); + // Confirm validity of the step mode and step size received VerifyOrReturnValue(commandData.stepMode != HueStepMode::kUnknownEnumValue, Status::InvalidCommand); VerifyOrReturnValue(commandData.stepSize != 0, Status::InvalidCommand); diff --git a/src/app/clusters/color-control-server/color-control-server.h b/src/app/clusters/color-control-server/color-control-server.h index 40ae30aeb2..c25313d251 100644 --- a/src/app/clusters/color-control-server/color-control-server.h +++ b/src/app/clusters/color-control-server/color-control-server.h @@ -294,6 +294,9 @@ class ColorControlServer MATTER_DM_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; static_assert(kColorControlClusterServerMaxEndpointCount <= kEmberInvalidEndpointIndex, "ColorControl endpoint count error"); + static constexpr uint16_t kMaxTransitionTime = 65534; // Max value as defined by the spec. + static constexpr uint16_t kMaxColorTemperatureMireds = 65279; // Max value as defined by the spec (0xFEFF). + #ifdef MATTER_DM_PLUGIN_COLOR_CONTROL_SERVER_HSV ColorHueTransitionState colorHueTransitionStates[kColorControlClusterServerMaxEndpointCount]; Color16uTransitionState colorSatTransitionStates[kColorControlClusterServerMaxEndpointCount]; From 603766a78b045ebc4d407d621394eb6ca5260fde Mon Sep 17 00:00:00 2001 From: Amine Alami <43780877+Alami-Amine@users.noreply.github.com> Date: Mon, 25 Nov 2024 14:16:16 +0100 Subject: [PATCH 084/219] Make Hash_SHA256_stream::IsInitialized() protected (#36633) --- src/crypto/CHIPCryptoPAL.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/crypto/CHIPCryptoPAL.h b/src/crypto/CHIPCryptoPAL.h index d2915f5d3c..8d6c8ba6fe 100644 --- a/src/crypto/CHIPCryptoPAL.h +++ b/src/crypto/CHIPCryptoPAL.h @@ -900,13 +900,6 @@ class Hash_SHA256_stream */ CHIP_ERROR Begin(); - /** - * @brief check if the digest computation has been initialized. - * - * @return True if the context is correctly initialized; otherwise, false. - */ - bool IsInitialized(); - /** * @brief Add some data to the digest computation, updating internal state. * @@ -948,6 +941,9 @@ class Hash_SHA256_stream void Clear(); private: + // Check if the digest computation has been initialized; implement this if your backend needs it. + bool IsInitialized(); + HashSHA256OpaqueContext mContext; }; From 2e34aa5a45912ccd40dbe7f75c3895b6c4d55ec1 Mon Sep 17 00:00:00 2001 From: Martin Girardot <165289184+Martin-NXP@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:05:00 +0100 Subject: [PATCH 085/219] [NXP] Update Thermostat ZAP files to fix IDM errors (#36612) Signed-off-by: Martin Girardot --- .../nxp/zap/thermostat_matter_br.matter | 154 +-- .../nxp/zap/thermostat_matter_br.zap | 1119 +++++++---------- .../nxp/zap/thermostat_matter_thread.matter | 142 +-- .../nxp/zap/thermostat_matter_thread.zap | 949 +++++++------- .../nxp/zap/thermostat_matter_wifi.matter | 140 +-- .../nxp/zap/thermostat_matter_wifi.zap | 897 ++++++------- .../nxp/common/DiagnosticDataProviderImpl.h | 2 - 7 files changed, 1415 insertions(+), 1988 deletions(-) diff --git a/examples/thermostat/nxp/zap/thermostat_matter_br.matter b/examples/thermostat/nxp/zap/thermostat_matter_br.matter index f38e2b130b..8a8d69fce6 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_br.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_br.matter @@ -341,83 +341,6 @@ cluster Identify = 3 { command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; } -/** Attributes and commands for group configuration and manipulation. */ -cluster Groups = 4 { - revision 4; - - bitmap Feature : bitmap32 { - kGroupNames = 0x1; - } - - bitmap NameSupportBitmap : bitmap8 { - kGroupNames = 0x80; - } - - readonly attribute NameSupportBitmap nameSupport = 0; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct AddGroupRequest { - group_id groupID = 0; - char_string<16> groupName = 1; - } - - response struct AddGroupResponse = 0 { - enum8 status = 0; - group_id groupID = 1; - } - - request struct ViewGroupRequest { - group_id groupID = 0; - } - - response struct ViewGroupResponse = 1 { - enum8 status = 0; - group_id groupID = 1; - char_string<16> groupName = 2; - } - - request struct GetGroupMembershipRequest { - group_id groupList[] = 0; - } - - response struct GetGroupMembershipResponse = 2 { - nullable int8u capacity = 0; - group_id groupList[] = 1; - } - - request struct RemoveGroupRequest { - group_id groupID = 0; - } - - response struct RemoveGroupResponse = 3 { - enum8 status = 0; - group_id groupID = 1; - } - - request struct AddGroupIfIdentifyingRequest { - group_id groupID = 0; - char_string<16> groupName = 1; - } - - /** Command description for AddGroup */ - fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; - /** Command description for ViewGroup */ - fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; - /** Command description for GetGroupMembership */ - fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; - /** Command description for RemoveGroup */ - fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; - /** Command description for RemoveAllGroups */ - fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; - /** Command description for AddGroupIfIdentifying */ - fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; -} - /** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ cluster Descriptor = 29 { revision 2; @@ -2249,6 +2172,7 @@ provisional cluster ThreadBorderRouterManagement = 1106 { endpoint 0 { device type ma_rootdevice = 22, version 1; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -2257,6 +2181,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -2265,10 +2192,11 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; callback attribute clusterRevision; @@ -2276,25 +2204,17 @@ endpoint 0 { server cluster BasicInformation { emits event StartUp; - emits event ShutDown; - emits event Leave; callback attribute dataModelRevision; callback attribute vendorName; callback attribute vendorID; callback attribute productName; callback attribute productID; - persist attribute nodeLabel; + ram attribute nodeLabel; callback attribute location; callback attribute hardwareVersion; callback attribute hardwareVersionString; callback attribute softwareVersion; callback attribute softwareVersionString; - callback attribute manufacturingDate; - callback attribute partNumber; - callback attribute productURL; - callback attribute productLabel; - callback attribute serialNumber; - persist attribute localConfigDisabled default = 0; callback attribute uniqueID; callback attribute capabilityMinima; callback attribute specificationVersion; @@ -2303,7 +2223,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -2314,6 +2234,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2326,8 +2249,11 @@ endpoint 0 { callback attribute regulatoryConfig; callback attribute locationCapability; callback attribute supportsConcurrentConnection; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -2351,7 +2277,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 1; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -2404,9 +2330,14 @@ endpoint 0 { callback attribute attributeList; callback attribute featureMap; ram attribute clusterRevision default = 1; + + handle command ResetWatermarks; } server cluster WiFiNetworkDiagnostics { + emits event Disconnection; + emits event AssociationFailure; + emits event ConnectionStatus; callback attribute bssid; callback attribute securityType; callback attribute wiFiVersion; @@ -2423,7 +2354,7 @@ endpoint 0 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; + ram attribute featureMap default = 3; ram attribute clusterRevision default = 1; handle command ResetCounts; @@ -2433,6 +2364,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2447,6 +2381,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2469,6 +2406,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2492,29 +2432,12 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; } - server cluster Groups { - ram attribute nameSupport; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; - - handle command AddGroup; - handle command AddGroupResponse; - handle command ViewGroup; - handle command ViewGroupResponse; - handle command GetGroupMembership; - handle command GetGroupMembershipResponse; - handle command RemoveGroup; - handle command RemoveGroupResponse; - handle command RemoveAllGroups; - handle command AddGroupIfIdentifying; - } - server cluster Descriptor { callback attribute deviceTypeList; callback attribute serverList; @@ -2557,7 +2480,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x3; - ram attribute clusterRevision default = 7; + ram attribute clusterRevision default = 8; handle command SetpointRaiseLower; } @@ -2593,8 +2516,8 @@ endpoint 2 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 2; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -2665,9 +2588,6 @@ endpoint 2 { callback attribute rxErrSecCount; callback attribute rxErrFcsCount; callback attribute rxErrOtherCount; - callback attribute activeTimestamp; - callback attribute pendingTimestamp; - callback attribute delay; callback attribute securityPolicy; callback attribute channelPage0Mask; callback attribute operationalDatasetComponents; @@ -2675,8 +2595,8 @@ endpoint 2 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 2; + ram attribute featureMap default = 0x000F; + ram attribute clusterRevision default = 3; handle command ResetCounts; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_br.zap b/examples/thermostat/nxp/zap/thermostat_matter_br.zap index ea67cd0066..b4973ba5ca 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_br.zap +++ b/examples/thermostat/nxp/zap/thermostat_matter_br.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -38,27 +38,38 @@ "id": 1, "name": "MA-rootdevice", "deviceTypeRef": { - "code": 22, + "code": 18, "profileId": 259, - "label": "MA-rootdevice", - "name": "MA-rootdevice" + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 }, "deviceTypes": [ + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 + }, { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 1 } ], "deviceVersions": [ + 1, 1 ], "deviceIdentifiers": [ + 18, 22 ], - "deviceTypeName": "MA-rootdevice", - "deviceTypeCode": 22, + "deviceTypeName": "MA-otarequestor", + "deviceTypeCode": 18, "deviceTypeProfileId": 259, "clusters": [ { @@ -133,6 +144,54 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -192,11 +251,11 @@ "reportableChange": 0 }, { - "name": "Extension", - "code": 1, + "name": "SubjectsPerAccessControlEntry", + "code": 2, "mfgCode": null, "side": "server", - "type": "array", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -208,8 +267,8 @@ "reportableChange": 0 }, { - "name": "SubjectsPerAccessControlEntry", - "code": 2, + "name": "TargetsPerAccessControlEntry", + "code": 3, "mfgCode": null, "side": "server", "type": "int16u", @@ -224,8 +283,8 @@ "reportableChange": 0 }, { - "name": "TargetsPerAccessControlEntry", - "code": 3, + "name": "AccessControlEntriesPerFabric", + "code": 4, "mfgCode": null, "side": "server", "type": "int16u", @@ -240,11 +299,27 @@ "reportableChange": 0 }, { - "name": "AccessControlEntriesPerFabric", - "code": 4, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -341,8 +416,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -357,8 +432,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -373,8 +448,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -389,8 +464,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -405,8 +480,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -416,13 +491,13 @@ "side": "server", "type": "char_string", "included": 1, - "storageOption": "NVM", + "storageOption": "RAM", "singleton": 1, "bounded": 0, "defaultValue": "", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -437,8 +512,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -453,8 +528,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -469,8 +544,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -485,8 +560,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -501,104 +576,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ManufacturingDate", - "code": 11, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PartNumber", - "code": 12, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductURL", - "code": 13, - "mfgCode": null, - "side": "server", - "type": "long_char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductLabel", - "code": 14, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SerialNumber", - "code": 15, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "LocalConfigDisabled", - "code": 16, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -613,8 +592,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -625,7 +604,7 @@ "type": "CapabilityMinimaStruct", "included": 1, "storageOption": "External", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": null, "reportable": 1, @@ -697,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -737,7 +700,7 @@ "type": "bitmap32", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": "0", "reportable": 1, @@ -755,10 +718,10 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 } ], @@ -769,20 +732,6 @@ "mfgCode": null, "side": "server", "included": 1 - }, - { - "name": "ShutDown", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1 - }, - { - "name": "Leave", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1 } ] }, @@ -918,6 +867,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1113,6 +1110,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1139,7 +1184,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1405,22 +1450,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1463,7 +1492,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1529,22 +1558,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1757,22 +1770,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1839,6 +1836,16 @@ "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "ThreadMetrics", @@ -1936,22 +1943,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2260,22 +2251,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2302,7 +2277,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2324,6 +2299,29 @@ "maxInterval": 65344, "reportableChange": 0 } + ], + "events": [ + { + "name": "Disconnection", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AssociationFailure", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ConnectionStatus", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } ] }, { @@ -2400,6 +2398,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -2636,6 +2682,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -2792,6 +2886,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -2835,14 +2977,16 @@ "code": 769, "profileId": 259, "label": "MA-thermostat", - "name": "MA-thermostat" + "name": "MA-thermostat", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 769, "profileId": 259, "label": "MA-thermostat", - "name": "MA-thermostat" + "name": "MA-thermostat", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -2877,270 +3021,114 @@ "mfgCode": null, "source": "client", "isIncoming": 0, - "isEnabled": 1 - } - ] - }, - { - "name": "Identify", - "code": 3, - "mfgCode": null, - "define": "IDENTIFY_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "Identify", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "TriggerEffect", - "code": 64, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "IdentifyTime", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0000", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "IdentifyType", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "IdentifyTypeEnum", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "4", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 + "isEnabled": 1 } ] }, { - "name": "Groups", - "code": 4, + "name": "Identify", + "code": 3, "mfgCode": null, - "define": "GROUPS_CLUSTER", + "define": "IDENTIFY_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "AddGroup", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddGroupResponse", + "name": "Identify", "code": 0, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "ViewGroup", - "code": 1, - "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "ViewGroupResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "GetGroupMembership", - "code": 2, + "name": "TriggerEffect", + "code": 64, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, + } + ], + "attributes": [ { - "name": "GetGroupMembershipResponse", - "code": 2, + "name": "IdentifyTime", + "code": 0, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 }, { - "name": "RemoveGroup", - "code": 3, + "name": "IdentifyType", + "code": 1, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "RemoveGroupResponse", - "code": 3, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "RemoveAllGroups", - "code": 4, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "AddGroupIfIdentifying", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "NameSupport", - "code": 0, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "NameSupportBitmap", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -3169,7 +3157,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3307,22 +3295,6 @@ "maxInterval": 65344, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "FeatureMap", "code": 65532, @@ -3413,22 +3385,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3779,7 +3735,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "7", + "defaultValue": "8", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3796,20 +3752,23 @@ "code": 25, "profileId": 259, "label": "MA-secondary-network-interface", - "name": "MA-secondary-network-interface" + "name": "MA-secondary-network-interface", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 25, "profileId": 259, "label": "MA-secondary-network-interface", - "name": "MA-secondary-network-interface" + "name": "MA-secondary-network-interface", + "deviceTypeOrder": 0 }, { "code": 145, "profileId": 259, "label": "MA-thread-border-router", - "name": "MA-thread-border-router" + "name": "MA-thread-border-router", + "deviceTypeOrder": 1 } ], "deviceVersions": [ @@ -3928,22 +3887,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -4260,22 +4203,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -4302,7 +4229,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4318,7 +4245,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -5240,54 +5167,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "ActiveTimestamp", - "code": 56, - "mfgCode": null, - "side": "server", - "type": "int64u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "PendingTimestamp", - "code": 57, - "mfgCode": null, - "side": "server", - "type": "int64u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "Delay", - "code": 58, - "mfgCode": null, - "side": "server", - "type": "int32u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SecurityPolicy", "code": 59, @@ -5384,22 +5263,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -5426,7 +5289,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "0x000F", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -5442,7 +5305,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -5645,22 +5508,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter index 4c6b26a578..a2a2f2d93a 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_thread.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.matter @@ -341,83 +341,6 @@ cluster Identify = 3 { command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; } -/** Attributes and commands for group configuration and manipulation. */ -cluster Groups = 4 { - revision 4; - - bitmap Feature : bitmap32 { - kGroupNames = 0x1; - } - - bitmap NameSupportBitmap : bitmap8 { - kGroupNames = 0x80; - } - - readonly attribute NameSupportBitmap nameSupport = 0; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct AddGroupRequest { - group_id groupID = 0; - char_string<16> groupName = 1; - } - - response struct AddGroupResponse = 0 { - enum8 status = 0; - group_id groupID = 1; - } - - request struct ViewGroupRequest { - group_id groupID = 0; - } - - response struct ViewGroupResponse = 1 { - enum8 status = 0; - group_id groupID = 1; - char_string<16> groupName = 2; - } - - request struct GetGroupMembershipRequest { - group_id groupList[] = 0; - } - - response struct GetGroupMembershipResponse = 2 { - nullable int8u capacity = 0; - group_id groupList[] = 1; - } - - request struct RemoveGroupRequest { - group_id groupID = 0; - } - - response struct RemoveGroupResponse = 3 { - enum8 status = 0; - group_id groupID = 1; - } - - request struct AddGroupIfIdentifyingRequest { - group_id groupID = 0; - char_string<16> groupName = 1; - } - - /** Command description for AddGroup */ - fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; - /** Command description for ViewGroup */ - fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; - /** Command description for GetGroupMembership */ - fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; - /** Command description for RemoveGroup */ - fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; - /** Command description for RemoveAllGroups */ - fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; - /** Command description for AddGroupIfIdentifying */ - fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; -} - /** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ cluster Descriptor = 29 { revision 2; @@ -2128,6 +2051,7 @@ cluster Thermostat = 513 { endpoint 0 { device type ma_rootdevice = 22, version 1; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -2136,6 +2060,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -2144,10 +2071,11 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; callback attribute clusterRevision; @@ -2155,25 +2083,17 @@ endpoint 0 { server cluster BasicInformation { emits event StartUp; - emits event ShutDown; - emits event Leave; callback attribute dataModelRevision; callback attribute vendorName; callback attribute vendorID; callback attribute productName; callback attribute productID; - persist attribute nodeLabel; + ram attribute nodeLabel; callback attribute location; callback attribute hardwareVersion; callback attribute hardwareVersionString; callback attribute softwareVersion; callback attribute softwareVersionString; - callback attribute manufacturingDate; - callback attribute partNumber; - callback attribute productURL; - callback attribute productLabel; - callback attribute serialNumber; - persist attribute localConfigDisabled default = 0; callback attribute uniqueID; callback attribute capabilityMinima; callback attribute specificationVersion; @@ -2182,7 +2102,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -2193,6 +2113,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2205,8 +2128,11 @@ endpoint 0 { callback attribute regulatoryConfig; callback attribute locationCapability; callback attribute supportsConcurrentConnection; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -2235,7 +2161,6 @@ endpoint 0 { handle command ScanNetworks; handle command ScanNetworksResponse; - handle command AddOrUpdateWiFiNetwork; handle command AddOrUpdateThreadNetwork; handle command RemoveNetwork; handle command NetworkConfigResponse; @@ -2284,6 +2209,8 @@ endpoint 0 { callback attribute attributeList; callback attribute featureMap; ram attribute clusterRevision default = 1; + + handle command ResetWatermarks; } server cluster ThreadNetworkDiagnostics { @@ -2345,9 +2272,6 @@ endpoint 0 { callback attribute rxErrSecCount; callback attribute rxErrFcsCount; callback attribute rxErrOtherCount; - callback attribute activeTimestamp; - callback attribute pendingTimestamp; - callback attribute delay; callback attribute securityPolicy; callback attribute channelPage0Mask; callback attribute operationalDatasetComponents; @@ -2356,7 +2280,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x000F; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command ResetCounts; } @@ -2365,6 +2289,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2379,6 +2306,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2401,6 +2331,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2424,29 +2357,12 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; } - server cluster Groups { - ram attribute nameSupport; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; - - handle command AddGroup; - handle command AddGroupResponse; - handle command ViewGroup; - handle command ViewGroupResponse; - handle command GetGroupMembership; - handle command GetGroupMembershipResponse; - handle command RemoveGroup; - handle command RemoveGroupResponse; - handle command RemoveAllGroups; - handle command AddGroupIfIdentifying; - } - server cluster Descriptor { callback attribute deviceTypeList; callback attribute serverList; @@ -2489,7 +2405,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x3; - ram attribute clusterRevision default = 7; + ram attribute clusterRevision default = 8; handle command SetpointRaiseLower; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_thread.zap b/examples/thermostat/nxp/zap/thermostat_matter_thread.zap index 21241a6625..8917a97d42 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_thread.zap +++ b/examples/thermostat/nxp/zap/thermostat_matter_thread.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -38,27 +38,38 @@ "id": 1, "name": "MA-rootdevice", "deviceTypeRef": { - "code": 22, + "code": 18, "profileId": 259, - "label": "MA-rootdevice", - "name": "MA-rootdevice" + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 }, "deviceTypes": [ + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 + }, { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 1 } ], "deviceVersions": [ + 1, 1 ], "deviceIdentifiers": [ + 18, 22 ], - "deviceTypeName": "MA-rootdevice", - "deviceTypeCode": 22, + "deviceTypeName": "MA-otarequestor", + "deviceTypeCode": 18, "deviceTypeProfileId": 259, "clusters": [ { @@ -133,6 +144,54 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -192,11 +251,11 @@ "reportableChange": 0 }, { - "name": "Extension", - "code": 1, + "name": "SubjectsPerAccessControlEntry", + "code": 2, "mfgCode": null, "side": "server", - "type": "array", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -208,8 +267,8 @@ "reportableChange": 0 }, { - "name": "SubjectsPerAccessControlEntry", - "code": 2, + "name": "TargetsPerAccessControlEntry", + "code": 3, "mfgCode": null, "side": "server", "type": "int16u", @@ -224,8 +283,8 @@ "reportableChange": 0 }, { - "name": "TargetsPerAccessControlEntry", - "code": 3, + "name": "AccessControlEntriesPerFabric", + "code": 4, "mfgCode": null, "side": "server", "type": "int16u", @@ -240,11 +299,27 @@ "reportableChange": 0 }, { - "name": "AccessControlEntriesPerFabric", - "code": 4, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -341,8 +416,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -357,8 +432,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -373,8 +448,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -389,8 +464,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -405,8 +480,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -416,13 +491,13 @@ "side": "server", "type": "char_string", "included": 1, - "storageOption": "NVM", + "storageOption": "RAM", "singleton": 1, "bounded": 0, "defaultValue": "", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -437,8 +512,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -453,8 +528,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -469,8 +544,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -485,8 +560,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -501,104 +576,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ManufacturingDate", - "code": 11, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PartNumber", - "code": 12, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductURL", - "code": 13, - "mfgCode": null, - "side": "server", - "type": "long_char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductLabel", - "code": 14, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SerialNumber", - "code": 15, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "LocalConfigDisabled", - "code": 16, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -613,8 +592,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -625,7 +604,7 @@ "type": "CapabilityMinimaStruct", "included": 1, "storageOption": "External", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": null, "reportable": 1, @@ -697,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -737,7 +700,7 @@ "type": "bitmap32", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": "0", "reportable": 1, @@ -755,10 +718,10 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 } ], @@ -769,20 +732,6 @@ "mfgCode": null, "side": "server", "included": 1 - }, - { - "name": "ShutDown", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1 - }, - { - "name": "Leave", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1 } ] }, @@ -918,6 +867,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1034,43 +1031,91 @@ ], "attributes": [ { - "name": "Breadcrumb", - "code": 0, + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0000000000000000", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "BasicCommissioningInfo", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "BasicCommissioningInfo", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RegulatoryConfig", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "RegulatoryLocationTypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LocationCapability", + "code": 3, "mfgCode": null, "side": "server", - "type": "int64u", + "type": "RegulatoryLocationTypeEnum", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "BasicCommissioningInfo", - "code": 1, + "name": "SupportsConcurrentConnection", + "code": 4, "mfgCode": null, "side": "server", - "type": "BasicCommissioningInfo", + "type": "boolean", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "RegulatoryConfig", - "code": 2, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "RegulatoryLocationTypeEnum", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1082,11 +1127,11 @@ "reportableChange": 0 }, { - "name": "LocationCapability", - "code": 3, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "RegulatoryLocationTypeEnum", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1098,11 +1143,11 @@ "reportableChange": 0 }, { - "name": "SupportsConcurrentConnection", - "code": 4, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "boolean", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1139,7 +1184,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1171,14 +1216,6 @@ "isIncoming": 0, "isEnabled": 1 }, - { - "name": "AddOrUpdateWiFiNetwork", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, { "name": "AddOrUpdateThreadNetwork", "code": 3, @@ -1421,22 +1458,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1545,22 +1566,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1773,22 +1778,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1855,6 +1844,16 @@ "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "ThreadMetrics", @@ -1952,22 +1951,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2932,54 +2915,6 @@ "maxInterval": 65344, "reportableChange": 0 }, - { - "name": "ActiveTimestamp", - "code": 56, - "mfgCode": null, - "side": "server", - "type": "int64u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "PendingTimestamp", - "code": 57, - "mfgCode": null, - "side": "server", - "type": "int64u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "Delay", - "code": 58, - "mfgCode": null, - "side": "server", - "type": "int32u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SecurityPolicy", "code": 59, @@ -3118,7 +3053,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3216,6 +3151,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3368,13 +3351,61 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "Fabrics", - "code": 1, + "name": "TrustedRootCertificates", + "code": 4, "mfgCode": null, "side": "server", "type": "array", @@ -3389,8 +3420,8 @@ "reportableChange": 0 }, { - "name": "SupportedFabrics", - "code": 2, + "name": "CurrentFabricIndex", + "code": 5, "mfgCode": null, "side": "server", "type": "int8u", @@ -3400,29 +3431,29 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CommissionedFabrics", - "code": 3, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "TrustedRootCertificates", - "code": 4, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -3432,16 +3463,16 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CurrentFabricIndex", - "code": 5, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -3608,6 +3639,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -3651,14 +3730,16 @@ "code": 769, "profileId": 259, "label": "MA-thermostat", - "name": "MA-thermostat" + "name": "MA-thermostat", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 769, "profileId": 259, "label": "MA-thermostat", - "name": "MA-thermostat" + "name": "MA-thermostat", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -3787,22 +3868,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3845,147 +3910,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Groups", - "code": 4, - "mfgCode": null, - "define": "GROUPS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "AddGroup", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddGroupResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "ViewGroup", - "code": 1, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ViewGroupResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "GetGroupMembership", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "GetGroupMembershipResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "RemoveGroup", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "RemoveGroupResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "RemoveAllGroups", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddGroupIfIdentifying", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "NameSupport", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "NameSupportBitmap", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -4123,22 +4048,6 @@ "maxInterval": 65344, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "FeatureMap", "code": 65532, @@ -4229,22 +4138,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -4595,7 +4488,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "7", + "defaultValue": "8", "reportable": 1, "minInterval": 0, "maxInterval": 65344, diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter index 9b09b05416..b5b24560e3 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.matter @@ -341,83 +341,6 @@ cluster Identify = 3 { command access(invoke: manage) TriggerEffect(TriggerEffectRequest): DefaultSuccess = 64; } -/** Attributes and commands for group configuration and manipulation. */ -cluster Groups = 4 { - revision 4; - - bitmap Feature : bitmap32 { - kGroupNames = 0x1; - } - - bitmap NameSupportBitmap : bitmap8 { - kGroupNames = 0x80; - } - - readonly attribute NameSupportBitmap nameSupport = 0; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct AddGroupRequest { - group_id groupID = 0; - char_string<16> groupName = 1; - } - - response struct AddGroupResponse = 0 { - enum8 status = 0; - group_id groupID = 1; - } - - request struct ViewGroupRequest { - group_id groupID = 0; - } - - response struct ViewGroupResponse = 1 { - enum8 status = 0; - group_id groupID = 1; - char_string<16> groupName = 2; - } - - request struct GetGroupMembershipRequest { - group_id groupList[] = 0; - } - - response struct GetGroupMembershipResponse = 2 { - nullable int8u capacity = 0; - group_id groupList[] = 1; - } - - request struct RemoveGroupRequest { - group_id groupID = 0; - } - - response struct RemoveGroupResponse = 3 { - enum8 status = 0; - group_id groupID = 1; - } - - request struct AddGroupIfIdentifyingRequest { - group_id groupID = 0; - char_string<16> groupName = 1; - } - - /** Command description for AddGroup */ - fabric command access(invoke: manage) AddGroup(AddGroupRequest): AddGroupResponse = 0; - /** Command description for ViewGroup */ - fabric command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; - /** Command description for GetGroupMembership */ - fabric command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; - /** Command description for RemoveGroup */ - fabric command access(invoke: manage) RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; - /** Command description for RemoveAllGroups */ - fabric command access(invoke: manage) RemoveAllGroups(): DefaultSuccess = 4; - /** Command description for AddGroupIfIdentifying */ - fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; -} - /** The Descriptor Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for describing a node, its endpoints and clusters. */ cluster Descriptor = 29 { revision 2; @@ -2039,6 +1962,7 @@ cluster Thermostat = 513 { endpoint 0 { device type ma_rootdevice = 22, version 1; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -2047,6 +1971,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -2055,10 +1982,11 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; callback attribute clusterRevision; @@ -2066,25 +1994,17 @@ endpoint 0 { server cluster BasicInformation { emits event StartUp; - emits event ShutDown; - emits event Leave; callback attribute dataModelRevision; callback attribute vendorName; callback attribute vendorID; callback attribute productName; callback attribute productID; - persist attribute nodeLabel; + ram attribute nodeLabel; callback attribute location; callback attribute hardwareVersion; callback attribute hardwareVersionString; callback attribute softwareVersion; callback attribute softwareVersionString; - callback attribute manufacturingDate; - callback attribute partNumber; - callback attribute productURL; - callback attribute productLabel; - callback attribute serialNumber; - persist attribute localConfigDisabled default = 0; callback attribute uniqueID; callback attribute capabilityMinima; callback attribute specificationVersion; @@ -2093,7 +2013,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster OtaSoftwareUpdateRequestor { @@ -2104,6 +2024,9 @@ endpoint 0 { ram attribute updatePossible default = 1; ram attribute updateState default = 0; ram attribute updateStateProgress default = 0; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2116,8 +2039,11 @@ endpoint 0 { callback attribute regulatoryConfig; callback attribute locationCapability; callback attribute supportsConcurrentConnection; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -2141,7 +2067,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 1; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -2194,6 +2120,8 @@ endpoint 0 { callback attribute attributeList; callback attribute featureMap; ram attribute clusterRevision default = 1; + + handle command ResetWatermarks; } server cluster WiFiNetworkDiagnostics { @@ -2216,7 +2144,7 @@ endpoint 0 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; + ram attribute featureMap default = 3; ram attribute clusterRevision default = 1; handle command ResetCounts; @@ -2226,6 +2154,9 @@ endpoint 0 { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2240,6 +2171,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2262,6 +2196,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2285,29 +2222,12 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; } - server cluster Groups { - ram attribute nameSupport; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; - - handle command AddGroup; - handle command AddGroupResponse; - handle command ViewGroup; - handle command ViewGroupResponse; - handle command GetGroupMembership; - handle command GetGroupMembershipResponse; - handle command RemoveGroup; - handle command RemoveGroupResponse; - handle command RemoveAllGroups; - handle command AddGroupIfIdentifying; - } - server cluster Descriptor { callback attribute deviceTypeList; callback attribute serverList; @@ -2350,7 +2270,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0x3; - ram attribute clusterRevision default = 7; + ram attribute clusterRevision default = 8; handle command SetpointRaiseLower; } diff --git a/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap b/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap index 9a50852ab5..7012d1ba11 100644 --- a/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap +++ b/examples/thermostat/nxp/zap/thermostat_matter_wifi.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -38,27 +38,38 @@ "id": 1, "name": "MA-rootdevice", "deviceTypeRef": { - "code": 22, + "code": 18, "profileId": 259, - "label": "MA-rootdevice", - "name": "MA-rootdevice" + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 }, "deviceTypes": [ + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 + }, { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 1 } ], "deviceVersions": [ + 1, 1 ], "deviceIdentifiers": [ + 18, 22 ], - "deviceTypeName": "MA-rootdevice", - "deviceTypeCode": 22, + "deviceTypeName": "MA-otarequestor", + "deviceTypeCode": 18, "deviceTypeProfileId": 259, "clusters": [ { @@ -133,6 +144,54 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -192,11 +251,11 @@ "reportableChange": 0 }, { - "name": "Extension", - "code": 1, + "name": "SubjectsPerAccessControlEntry", + "code": 2, "mfgCode": null, "side": "server", - "type": "array", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -208,8 +267,8 @@ "reportableChange": 0 }, { - "name": "SubjectsPerAccessControlEntry", - "code": 2, + "name": "TargetsPerAccessControlEntry", + "code": 3, "mfgCode": null, "side": "server", "type": "int16u", @@ -224,8 +283,8 @@ "reportableChange": 0 }, { - "name": "TargetsPerAccessControlEntry", - "code": 3, + "name": "AccessControlEntriesPerFabric", + "code": 4, "mfgCode": null, "side": "server", "type": "int16u", @@ -240,11 +299,27 @@ "reportableChange": 0 }, { - "name": "AccessControlEntriesPerFabric", - "code": 4, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -341,8 +416,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -357,8 +432,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -373,8 +448,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -389,8 +464,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -405,8 +480,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -416,13 +491,13 @@ "side": "server", "type": "char_string", "included": 1, - "storageOption": "NVM", + "storageOption": "RAM", "singleton": 1, "bounded": 0, "defaultValue": "", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -437,8 +512,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -453,8 +528,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -469,8 +544,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -485,8 +560,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -501,104 +576,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ManufacturingDate", - "code": 11, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PartNumber", - "code": 12, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductURL", - "code": 13, - "mfgCode": null, - "side": "server", - "type": "long_char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductLabel", - "code": 14, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SerialNumber", - "code": 15, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "LocalConfigDisabled", - "code": 16, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -613,8 +592,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -625,7 +604,7 @@ "type": "CapabilityMinimaStruct", "included": 1, "storageOption": "External", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": null, "reportable": 1, @@ -697,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -737,7 +700,7 @@ "type": "bitmap32", "included": 1, "storageOption": "RAM", - "singleton": 0, + "singleton": 1, "bounded": 0, "defaultValue": "0", "reportable": 1, @@ -755,10 +718,10 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 } ], @@ -769,20 +732,6 @@ "mfgCode": null, "side": "server", "included": 1 - }, - { - "name": "ShutDown", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1 - }, - { - "name": "Leave", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1 } ] }, @@ -877,42 +826,90 @@ "side": "server", "type": "boolean", "included": 1, - "storageOption": "RAM", + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateState", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "UpdateStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "UpdateStateProgress", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "UpdateState", - "code": 2, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "UpdateStateEnum", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "UpdateStateProgress", - "code": 3, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -1113,6 +1110,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1139,7 +1184,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1405,22 +1450,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1463,7 +1492,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1529,22 +1558,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1757,22 +1770,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1839,6 +1836,16 @@ "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "ThreadMetrics", @@ -1936,22 +1943,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2174,7 +2165,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2222,7 +2213,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2260,22 +2251,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2302,7 +2277,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2423,6 +2398,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -2575,13 +2598,61 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "Fabrics", - "code": 1, + "name": "TrustedRootCertificates", + "code": 4, "mfgCode": null, "side": "server", "type": "array", @@ -2596,8 +2667,8 @@ "reportableChange": 0 }, { - "name": "SupportedFabrics", - "code": 2, + "name": "CurrentFabricIndex", + "code": 5, "mfgCode": null, "side": "server", "type": "int8u", @@ -2607,29 +2678,29 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CommissionedFabrics", - "code": 3, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "TrustedRootCertificates", - "code": 4, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -2639,16 +2710,16 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CurrentFabricIndex", - "code": 5, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -2815,6 +2886,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -2858,14 +2977,16 @@ "code": 769, "profileId": 259, "label": "MA-thermostat", - "name": "MA-thermostat" + "name": "MA-thermostat", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 769, "profileId": 259, "label": "MA-thermostat", - "name": "MA-thermostat" + "name": "MA-thermostat", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -2994,22 +3115,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3052,147 +3157,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, - { - "name": "Groups", - "code": 4, - "mfgCode": null, - "define": "GROUPS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "AddGroup", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddGroupResponse", - "code": 0, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "ViewGroup", - "code": 1, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "ViewGroupResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "GetGroupMembership", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "GetGroupMembershipResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "RemoveGroup", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "RemoveGroupResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "RemoveAllGroups", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddGroupIfIdentifying", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "NameSupport", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "NameSupportBitmap", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -3330,22 +3295,6 @@ "maxInterval": 65344, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "FeatureMap", "code": 65532, @@ -3436,22 +3385,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3802,7 +3735,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "7", + "defaultValue": "8", "reportable": 1, "minInterval": 0, "maxInterval": 65344, diff --git a/src/platform/nxp/common/DiagnosticDataProviderImpl.h b/src/platform/nxp/common/DiagnosticDataProviderImpl.h index 27b2e35365..2137d63d38 100644 --- a/src/platform/nxp/common/DiagnosticDataProviderImpl.h +++ b/src/platform/nxp/common/DiagnosticDataProviderImpl.h @@ -40,9 +40,7 @@ class DiagnosticDataProviderImpl : public DiagnosticDataProvider // ===== Methods that implement the PlatformManager abstract interface. -#if NXP_USE_MML bool SupportsWatermarks() override { return true; } -#endif CHIP_ERROR GetCurrentHeapFree(uint64_t & currentHeapFree) override; CHIP_ERROR GetCurrentHeapUsed(uint64_t & currentHeapUsed) override; CHIP_ERROR GetCurrentHeapHighWatermark(uint64_t & currentHeapHighWatermark) override; From 6fda73ab5a7ef1ec792e9873f116dc44a46ffbc1 Mon Sep 17 00:00:00 2001 From: Andy Salisbury Date: Mon, 25 Nov 2024 12:12:08 -0500 Subject: [PATCH 086/219] BDX transfer support for Python tests (#34821) * Add the python-C++ translation. * Add a BDX transfer server to handle unsolicited BDX init messages. * Add the manager to implement the transfer pool. * Add the initial implementation of a BDX transfer. * Use BdxTransfer in the other classes. * Update constructors to set the delegates etc. correctly. * Implement the C++ side of the barrier. Move the data callback into the transfer delegate. * Add a way to map the transfer to the python contexts. * Fix some of the minor TODOs. * Add init/shutdown to the transfer server. * Start on the implementation of the Python side. Also add the transfer obtained context to the C++ methods relating to expecting transfers. * Listen for all BDX protocol messages rather than just the init messages. * Fix minor issues in the transfer server. * Implement a good chunk of the python side. * Fix compile errors. * Fix a number of issues preventing the BDX python code from running at all. * Return the results of the python-C methods. * Fix the async-ness of the methods that prepare the system to receive a BDX transfer. Also run the python BDX initialisation. * Initialise the BDX transfer server. Also ignore the BDX transfer server implementation that only handles diagnostic logs. * Fixes necessary to await on the future from PrepareToReceive/SendBdxData. * Call Responder::PrepareForTransfer from BdxTransfer. * Correctly schedule satisfying the future on the event loop. * Use the real property to determine if a PyChipError was a success. * Fix sending the accept message. * Acknowledge received blocks so the BDX transfer continues. Also don't ignore all messages after the init. * Fix the parameters of the python callback methods. * Add another async transaction class to handle the transfer completed callback. * Add comments to the C++ code. * Add a test for the BDX transfer that uses the diagnostic logs cluster. * Move the calls to release a transfer out of the manager so it works the way one would expect. * Delay releasing the C++ BDX transfer object until after it's no longer in use. * Verify the diagnostic logs response is a success. * Restyled by whitespace * Restyled by clang-format * Restyled by gn * Restyled by autopep8 * Restyled by isort * Improve BdxTransferManager's comments. * Use a vector for the data to send over a BDX transfer rather than a raw pointer. * Minor renames. * Improve the error message when the BDX transfer pool is exhausted. * Minor fixes. * remove a check that was inadvertently kept. * print a log message when something that shouldn't happen inevitably does. * use user_params to get the end user support log test parameter. * Pass the status report's status code up the stack. * Merge the BDX transfer server into the manager. * Rename BdxTransferManager to TestBdxTransferServer. * Minor cleanup. * Rename TransferData to TransferInfo. * Change `!=` to `is not` in python. * Add missing type annotation. * Improve the documentation of the ownership in the C++ side. * Restyled by clang-format * Restyled by autopep8 * Update the new test to work with the new formatting. Also remove an unnecessary conversion to bytearray. * Lint fixes. * Fix clang-tidy errors. * Several fixes suggested by Andrei. * Fix a name in a comment. * Fix issues preventing test from working. Also: * Split the accept function into one for sending data and one for receiving data. * Return bytes instead of a bytearray when receiving data. * Add typing to the data callback. * Rename the methods that accept transfers so it's clear which way the data is flowing. * Add doc comments to the Python classes and methods. * Fix issues found by mypy. * Restyled by clang-format * Restyled by autopep8 * Fix python lint error. * Explicitly truncate the status code when generating the error. * Generate the diagnostic log to transfer in the test. --------- Co-authored-by: Restyled.io --- src/controller/python/BUILD.gn | 10 + src/controller/python/chip/ChipDeviceCtrl.py | 31 +++ src/controller/python/chip/ChipStack.py | 2 + src/controller/python/chip/bdx/Bdx.py | 230 +++++++++++++++ src/controller/python/chip/bdx/BdxProtocol.py | 23 ++ src/controller/python/chip/bdx/BdxTransfer.py | 81 ++++++ src/controller/python/chip/bdx/__init__.py | 27 ++ .../python/chip/bdx/bdx-transfer.cpp | 214 ++++++++++++++ src/controller/python/chip/bdx/bdx-transfer.h | 90 ++++++ src/controller/python/chip/bdx/bdx.cpp | 263 ++++++++++++++++++ .../chip/bdx/test-bdx-transfer-server.cpp | 95 +++++++ .../chip/bdx/test-bdx-transfer-server.h | 69 +++++ src/python_testing/TestBdxTransfer.py | 119 ++++++++ 13 files changed, 1254 insertions(+) create mode 100644 src/controller/python/chip/bdx/Bdx.py create mode 100644 src/controller/python/chip/bdx/BdxProtocol.py create mode 100644 src/controller/python/chip/bdx/BdxTransfer.py create mode 100644 src/controller/python/chip/bdx/__init__.py create mode 100644 src/controller/python/chip/bdx/bdx-transfer.cpp create mode 100644 src/controller/python/chip/bdx/bdx-transfer.h create mode 100644 src/controller/python/chip/bdx/bdx.cpp create mode 100644 src/controller/python/chip/bdx/test-bdx-transfer-server.cpp create mode 100644 src/controller/python/chip/bdx/test-bdx-transfer-server.h create mode 100644 src/python_testing/TestBdxTransfer.py diff --git a/src/controller/python/BUILD.gn b/src/controller/python/BUILD.gn index 58d9cb1f7c..a90f59f2f3 100644 --- a/src/controller/python/BUILD.gn +++ b/src/controller/python/BUILD.gn @@ -63,6 +63,11 @@ shared_library("ChipDeviceCtrl") { "ChipDeviceController-StorageDelegate.cpp", "ChipDeviceController-StorageDelegate.h", "OpCredsBinding.cpp", + "chip/bdx/bdx-transfer.cpp", + "chip/bdx/bdx-transfer.h", + "chip/bdx/bdx.cpp", + "chip/bdx/test-bdx-transfer-server.cpp", + "chip/bdx/test-bdx-transfer-server.h", "chip/clusters/attribute.cpp", "chip/clusters/command.cpp", "chip/commissioning/PlaceholderOperationalCredentialsIssuer.h", @@ -166,6 +171,10 @@ chip_python_wheel_action("chip-core") { "chip/ChipStack.py", "chip/FabricAdmin.py", "chip/__init__.py", + "chip/bdx/Bdx.py", + "chip/bdx/BdxProtocol.py", + "chip/bdx/BdxTransfer.py", + "chip/bdx/__init__.py", "chip/ble/__init__.py", "chip/ble/commissioning/__init__.py", "chip/ble/get_adapters.py", @@ -235,6 +244,7 @@ chip_python_wheel_action("chip-core") { py_packages = [ "chip", + "chip.bdx", "chip.ble", "chip.ble.commissioning", "chip.configuration", diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py index 8c751f7f79..1e8f74fbd2 100644 --- a/src/controller/python/chip/ChipDeviceCtrl.py +++ b/src/controller/python/chip/ChipDeviceCtrl.py @@ -48,6 +48,7 @@ from . import FabricAdmin from . import clusters as Clusters from . import discovery +from .bdx import Bdx from .clusters import Attribute as ClusterAttribute from .clusters import ClusterObjects as ClusterObjects from .clusters import Command as ClusterCommand @@ -1343,6 +1344,36 @@ def WriteGroupAttribute( # An empty list is the expected return for sending group write attribute. return [] + def TestOnlyPrepareToReceiveBdxData(self) -> asyncio.Future: + ''' + Sets up the system to expect a node to initiate a BDX transfer. The transfer will send data here. + + Returns: + - a future that will yield a BdxTransfer with the init message from the transfer. + ''' + self.CheckIsActive() + + eventLoop = asyncio.get_running_loop() + future = eventLoop.create_future() + + Bdx.PrepareToReceiveBdxData(future).raise_on_error() + return future + + def TestOnlyPrepareToSendBdxData(self, data: bytes) -> asyncio.Future: + ''' + Sets up the system to expect a node to initiate a BDX transfer. The transfer will send data to the node. + + Returns: + - a future that will yield a BdxTransfer with the init message from the transfer. + ''' + self.CheckIsActive() + + eventLoop = asyncio.get_running_loop() + future = eventLoop.create_future() + + Bdx.PrepareToSendBdxData(future, data).raise_on_error() + return future + def _parseAttributePathTuple(self, pathTuple: typing.Union[ None, # Empty tuple, all wildcard typing.Tuple[int], # Endpoint diff --git a/src/controller/python/chip/ChipStack.py b/src/controller/python/chip/ChipStack.py index e029b77f0a..94ad734e37 100644 --- a/src/controller/python/chip/ChipStack.py +++ b/src/controller/python/chip/ChipStack.py @@ -36,6 +36,7 @@ import chip.native from chip.native import PyChipError +from .bdx import Bdx from .clusters import Attribute as ClusterAttribute from .clusters import Command as ClusterCommand from .exceptions import ChipStackError, ChipStackException, DeviceError @@ -175,6 +176,7 @@ def HandleChipThreadRun(callback): im.InitIMDelegate() ClusterAttribute.Init() ClusterCommand.Init() + Bdx.Init() builtins.chipStack = self diff --git a/src/controller/python/chip/bdx/Bdx.py b/src/controller/python/chip/bdx/Bdx.py new file mode 100644 index 0000000000..7641644465 --- /dev/null +++ b/src/controller/python/chip/bdx/Bdx.py @@ -0,0 +1,230 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# + +import asyncio +import builtins +import ctypes +from asyncio.futures import Future +from ctypes import CFUNCTYPE, POINTER, c_char_p, c_size_t, c_uint8, c_uint16, c_uint64, c_void_p, py_object +from typing import Callable, Optional + +import chip +from chip.native import PyChipError + +from . import BdxTransfer + +c_uint8_p = POINTER(c_uint8) + + +_OnTransferObtainedCallbackFunct = CFUNCTYPE( + None, py_object, c_void_p, c_uint8, c_uint16, c_uint64, c_uint64, c_uint8_p, c_uint16, c_uint8_p, c_size_t) +_OnFailedToObtainTransferCallbackFunct = CFUNCTYPE(None, py_object, PyChipError) +_OnDataReceivedCallbackFunct = CFUNCTYPE(None, py_object, c_uint8_p, c_size_t) +_OnTransferCompletedCallbackFunct = CFUNCTYPE(None, py_object, PyChipError) + + +class AsyncTransferObtainedTransaction: + ''' The Python context when obtaining a transfer. This is passed into the C++ code to be sent back to Python as part + of the callback when a transfer is obtained, and sets the result of the future after being called back. + ''' + + def __init__(self, future, event_loop, data=None): + self._future = future + self._data = data + self._event_loop = event_loop + + def _handleTransfer(self, bdxTransfer, initMessage: BdxTransfer.InitMessage): + transfer = BdxTransfer.BdxTransfer(bdx_transfer=bdxTransfer, init_message=initMessage, data=self._data) + self._future.set_result(transfer) + + def handleTransfer(self, bdxTransfer, initMessage: BdxTransfer.InitMessage): + self._event_loop.call_soon_threadsafe(self._handleTransfer, bdxTransfer, initMessage) + + def _handleError(self, result: PyChipError): + self._future.set_exception(result.to_exception()) + + def handleError(self, result: PyChipError): + self._event_loop.call_soon_threadsafe(self._handleError, result) + + +class AsyncTransferCompletedTransaction: + ''' The Python context when accepting a transfer. This is passed into the C++ code to be sent back to Python as part + of the callback when the transfer completes, and sets the result of the future after being called back. + ''' + + def __init__(self, future, event_loop): + self._future = future + self._event_loop = event_loop + + def _handleResult(self, result: PyChipError): + if result.is_success: + self._future.set_result(result) + else: + self._future.set_exception(result.to_exception()) + + def handleResult(self, result: PyChipError): + self._event_loop.call_soon_threadsafe(self._handleResult, result) + + +@_OnTransferObtainedCallbackFunct +def _OnTransferObtainedCallback(transaction: AsyncTransferObtainedTransaction, bdxTransfer, transferControlFlags: int, + maxBlockSize: int, startOffset: int, length: int, fileDesignator, fileDesignatorLength: int, + metadata, metadataLength: int): + fileDesignatorData = ctypes.string_at(fileDesignator, fileDesignatorLength) + metadataData = ctypes.string_at(metadata, metadataLength) + + initMessage = BdxTransfer.InitMessage( + transferControlFlags, + maxBlockSize, + startOffset, + length, + fileDesignatorData[:], + metadataData[:], + ) + + transaction.handleTransfer(bdxTransfer, initMessage) + + +@_OnFailedToObtainTransferCallbackFunct +def _OnFailedToObtainTransferCallback(transaction: AsyncTransferObtainedTransaction, result: PyChipError): + transaction.handleError(result) + + +@_OnDataReceivedCallbackFunct +def _OnDataReceivedCallback(context, dataBuffer: c_uint8_p, bufferLength: int): + data = ctypes.string_at(dataBuffer, bufferLength) + context(data) + + +@_OnTransferCompletedCallbackFunct +def _OnTransferCompletedCallback(transaction: AsyncTransferCompletedTransaction, result: PyChipError): + transaction.handleResult(result) + + +def _PrepareForBdxTransfer(future: Future, data: Optional[bytes]) -> PyChipError: + ''' Prepares the BDX system for a BDX transfer. The BDX transfer is set as the future's result. This must be called + before the BDX transfer is initiated. + + Returns the CHIP_ERROR result from the C++ side. + ''' + handle = chip.native.GetLibraryHandle() + transaction = AsyncTransferObtainedTransaction(future=future, event_loop=asyncio.get_running_loop(), data=data) + + ctypes.pythonapi.Py_IncRef(ctypes.py_object(transaction)) + res = builtins.chipStack.Call( + lambda: handle.pychip_Bdx_ExpectBdxTransfer(ctypes.py_object(transaction)) + ) + if not res.is_success: + ctypes.pythonapi.Py_DecRef(ctypes.py_object(transaction)) + return res + + +def PrepareToReceiveBdxData(future: Future) -> PyChipError: + ''' Prepares the BDX system for a BDX transfer where this device receives data. This must be called before the BDX + transfer is initiated. + + When a BDX transfer is found it's set as the future's result. If an error occurs while waiting it is set as the future's exception. + + Returns an error if there was an issue preparing to wait a BDX transfer. + ''' + return _PrepareForBdxTransfer(future, None) + + +def PrepareToSendBdxData(future: Future, data: bytes) -> PyChipError: + ''' Prepares the BDX system for a BDX transfer where this device sends data. This must be called before the BDX + transfer is initiated. + + When a BDX transfer is found it's set as the future's result. If an error occurs while waiting it is set as the future's exception. + + Returns an error if there was an issue preparing to wait a BDX transfer. + ''' + return _PrepareForBdxTransfer(future, data) + + +def AcceptTransferAndReceiveData(transfer: c_void_p, dataReceivedClosure: Callable[[bytes], None], transferComplete: Future): + ''' Accepts a BDX transfer with the intent of receiving data. + + The data will be returned block-by-block in dataReceivedClosure. + transferComplete will be fulfilled when the transfer completes. + + Returns an error if one is encountered while accepting the transfer. + ''' + handle = chip.native.GetLibraryHandle() + complete_transaction = AsyncTransferCompletedTransaction(future=transferComplete, event_loop=asyncio.get_running_loop()) + ctypes.pythonapi.Py_IncRef(ctypes.py_object(dataReceivedClosure)) + ctypes.pythonapi.Py_IncRef(ctypes.py_object(complete_transaction)) + res = builtins.chipStack.Call( + lambda: handle.pychip_Bdx_AcceptTransferAndReceiveData(transfer, dataReceivedClosure, complete_transaction) + ) + if not res.is_success: + ctypes.pythonapi.Py_DecRef(ctypes.py_object(dataReceivedClosure)) + ctypes.pythonapi.Py_DecRef(ctypes.py_object(complete_transaction)) + return res + + +def AcceptTransferAndSendData(transfer: c_void_p, data: bytearray, transferComplete: Future): + ''' Accepts a BDX transfer with the intent of sending data. + + The data will be copied by C++. + transferComplete will be fulfilled when the transfer completes. + + Returns an error if one is encountered while accepting the transfer. + ''' + handle = chip.native.GetLibraryHandle() + complete_transaction = AsyncTransferCompletedTransaction(future=transferComplete, event_loop=asyncio.get_running_loop()) + ctypes.pythonapi.Py_IncRef(ctypes.py_object(complete_transaction)) + res = builtins.chipStack.Call( + lambda: handle.pychip_Bdx_AcceptTransferAndSendData(transfer, c_char_p(data), len(data), complete_transaction) + ) + if not res.is_success: + ctypes.pythonapi.Py_DecRef(ctypes.py_object(complete_transaction)) + return res + + +async def RejectTransfer(transfer: c_void_p): + ''' Rejects a BDX transfer. + + Returns an error if one is encountered while rejecting the transfer. + ''' + handle = chip.native.GetLibraryHandle() + return await builtins.chipStack.CallAsyncWithResult( + lambda: handle.pychip_Bdx_RejectTransfer(transfer) + ) + + +def Init(): + handle = chip.native.GetLibraryHandle() + # Uses one of the type decorators as an indicator for everything being initialized. + if not handle.pychip_Bdx_ExpectBdxTransfer.argtypes: + setter = chip.native.NativeLibraryHandleMethodArguments(handle) + + setter.Set('pychip_Bdx_ExpectBdxTransfer', + PyChipError, [py_object]) + setter.Set('pychip_Bdx_StopExpectingBdxTransfer', + PyChipError, [py_object]) + setter.Set('pychip_Bdx_AcceptTransferAndReceiveData', + PyChipError, [c_void_p, py_object, py_object]) + setter.Set('pychip_Bdx_AcceptTransferAndSendData', + PyChipError, [c_void_p, c_uint8_p, c_size_t]) + setter.Set('pychip_Bdx_RejectTransfer', + PyChipError, [c_void_p]) + setter.Set('pychip_Bdx_InitCallbacks', None, [ + _OnTransferObtainedCallbackFunct, _OnFailedToObtainTransferCallbackFunct, _OnDataReceivedCallbackFunct, + _OnTransferCompletedCallbackFunct]) + + handle.pychip_Bdx_InitCallbacks( + _OnTransferObtainedCallback, _OnFailedToObtainTransferCallback, _OnDataReceivedCallback, _OnTransferCompletedCallback) diff --git a/src/controller/python/chip/bdx/BdxProtocol.py b/src/controller/python/chip/bdx/BdxProtocol.py new file mode 100644 index 0000000000..6d53fda44d --- /dev/null +++ b/src/controller/python/chip/bdx/BdxProtocol.py @@ -0,0 +1,23 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# + +# These BDX constants are defined in the spec. + +# SendInit/ReceiveInit Proposed Transfer Control field structure. +SENDER_DRIVE = 0x10 +RECEIVER_DRIVE = 0x20 +ASYNC = 0x40 diff --git a/src/controller/python/chip/bdx/BdxTransfer.py b/src/controller/python/chip/bdx/BdxTransfer.py new file mode 100644 index 0000000000..7e5ef630eb --- /dev/null +++ b/src/controller/python/chip/bdx/BdxTransfer.py @@ -0,0 +1,81 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# + +import asyncio +from ctypes import c_void_p +from dataclasses import dataclass +from typing import Optional + +from . import Bdx + + +@dataclass +class InitMessage: + ''' The details of the init message received at the start of a BDX transfer. + ''' + # The transfer control flag constants SENDER_DRIVE, RECEIVER_DRIVE, and ASYNC are defined in BdxProtocol.py. + TransferControlFlags: int + MaxBlockSize: int + StartOffset: int + Length: int + FileDesignator: bytes + Metadata: bytes + + +class BdxTransfer: + ''' A representation of a BDX transfer. + + This is created when a BDX init message is received, and stores the details of that init message. + The transfer can be accepted by calling accept_and_send_data or accept_and_receive_data. + The transfer can be rejected by calling reject. + ''' + + def __init__(self, bdx_transfer: c_void_p, init_message: InitMessage, data: Optional[bytes] = None): + self.init_message = init_message + self._bdx_transfer = bdx_transfer + # _data is a bytearray when receiving data, so the data to send is converted to one as well for consistency. + self._data = bytearray(data) if data else None + + async def accept_and_send_data(self) -> None: + ''' Accepts the transfer with the intent of sending data. + ''' + assert self._data is not None + eventLoop = asyncio.get_running_loop() + future = eventLoop.create_future() + res = Bdx.AcceptTransferAndSendData(self._bdx_transfer, self._data, future) + res.raise_on_error() + await future + + async def accept_and_receive_data(self) -> bytes: + ''' Accepts the transfer with the intent of receiving data. + + Returns the data received when the transfer is complete. + ''' + assert self._data is None + eventLoop = asyncio.get_running_loop() + future = eventLoop.create_future() + self._data = bytearray() + res = Bdx.AcceptTransferAndReceiveData(self._bdx_transfer, lambda data: self._data.extend(data), future) + res.raise_on_error() + await future + return bytes(self._data) + + async def reject(self) -> None: + ''' Rejects the transfer. + ''' + res = await Bdx.RejectTransfer(self._bdx_transfer) + res.raise_on_error() diff --git a/src/controller/python/chip/bdx/__init__.py b/src/controller/python/chip/bdx/__init__.py new file mode 100644 index 0000000000..8c3c1fb36a --- /dev/null +++ b/src/controller/python/chip/bdx/__init__.py @@ -0,0 +1,27 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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 +# Provides BDX Python APIs for CHIP. +# + +"""Provides BDX Python APIs for CHIP.""" + +from . import Bdx, BdxProtocol, BdxTransfer + +__all__ = ["Bdx", "BdxProtocol", "BdxTransfer", "InitMessage"] diff --git a/src/controller/python/chip/bdx/bdx-transfer.cpp b/src/controller/python/chip/bdx/bdx-transfer.cpp new file mode 100644 index 0000000000..f84fde9a14 --- /dev/null +++ b/src/controller/python/chip/bdx/bdx-transfer.cpp @@ -0,0 +1,214 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#include + +#include + +namespace chip { +namespace bdx { +namespace { + +constexpr uint32_t kMaxBdxBlockSize = 1024; +constexpr System::Clock::Timeout kBdxPollInterval = System::Clock::Milliseconds32(50); +constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60); + +} // namespace + +void BdxTransfer::SetDelegate(BdxTransfer::Delegate * delegate) +{ + mDelegate = delegate; +} + +CHIP_ERROR BdxTransfer::AcceptAndReceiveData() +{ + VerifyOrReturnError(mAwaitingAccept, CHIP_ERROR_INCORRECT_STATE); + mAwaitingAccept = false; + + TransferSession::TransferAcceptData acceptData; + acceptData.ControlMode = TransferControlFlags::kSenderDrive; + acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize(); + acceptData.StartOffset = mTransfer.GetStartOffset(); + acceptData.Length = mTransfer.GetTransferLength(); + return mTransfer.AcceptTransfer(acceptData); +} + +CHIP_ERROR BdxTransfer::AcceptAndSendData(const ByteSpan & data_to_send) +{ + VerifyOrReturnError(mAwaitingAccept, CHIP_ERROR_INCORRECT_STATE); + mAwaitingAccept = false; + mData.assign(data_to_send.begin(), data_to_send.end()); + mDataCount = data_to_send.size(); + + TransferSession::TransferAcceptData acceptData; + acceptData.ControlMode = TransferControlFlags::kReceiverDrive; + acceptData.MaxBlockSize = mTransfer.GetTransferBlockSize(); + acceptData.StartOffset = mTransfer.GetStartOffset(); + acceptData.Length = mTransfer.GetTransferLength(); + return mTransfer.AcceptTransfer(acceptData); +} + +CHIP_ERROR BdxTransfer::Reject() +{ + VerifyOrReturnError(mAwaitingAccept, CHIP_ERROR_INCORRECT_STATE); + mAwaitingAccept = false; + return mTransfer.RejectTransfer(StatusCode::kTransferFailedUnknownError); +} + +void BdxTransfer::HandleTransferSessionOutput(TransferSession::OutputEvent & event) +{ + ChipLogDetail(BDX, "Received event %s", event.ToString(event.EventType)); + + switch (event.EventType) + { + case TransferSession::OutputEventType::kInitReceived: + mAwaitingAccept = true; + mDelegate->InitMessageReceived(this, event.transferInitData); + break; + case TransferSession::OutputEventType::kStatusReceived: + ChipLogError(BDX, "Received StatusReport %x", ::chip::to_underlying(event.statusData.statusCode)); + EndSession(ChipError(ChipError::SdkPart::kIMClusterStatus, static_cast(event.statusData.statusCode))); + break; + case TransferSession::OutputEventType::kInternalError: + EndSession(CHIP_ERROR_INTERNAL); + break; + case TransferSession::OutputEventType::kTransferTimeout: + EndSession(CHIP_ERROR_TIMEOUT); + break; + case TransferSession::OutputEventType::kBlockReceived: + if (mDelegate) + { + ByteSpan data(event.blockdata.Data, event.blockdata.Length); + mDelegate->DataReceived(this, data); + mTransfer.PrepareBlockAck(); + } + else + { + ChipLogError(BDX, "Block received without a delegate!"); + } + break; + case TransferSession::OutputEventType::kMsgToSend: + SendMessage(event); + if (event.msgTypeData.HasMessageType(MessageType::BlockAckEOF)) + { + // TODO: Ending the session here means the StandaloneAck for the BlockAckEOF message hasn't been received. + EndSession(CHIP_NO_ERROR); + } + break; + case TransferSession::OutputEventType::kAckEOFReceived: + EndSession(CHIP_NO_ERROR); + break; + case TransferSession::OutputEventType::kQueryWithSkipReceived: + mDataTransferredCount = std::min(mDataTransferredCount + event.bytesToSkip.BytesToSkip, mDataCount); + SendBlock(); + break; + case TransferSession::OutputEventType::kQueryReceived: + SendBlock(); + break; + case TransferSession::OutputEventType::kAckReceived: + case TransferSession::OutputEventType::kAcceptReceived: + case TransferSession::OutputEventType::kNone: + // Nothing to do. + break; + default: + // Should never happen. + ChipLogError(BDX, "Unhandled BDX transfer session event type %d.", static_cast(event.EventType)); + chipDie(); + break; + } +} + +void BdxTransfer::EndSession(CHIP_ERROR result) +{ + if (mDelegate) + { + mDelegate->TransferCompleted(this, result); + } + ResetTransfer(); + if (mExchangeCtx) + { + mExchangeCtx->Close(); + } +} + +void BdxTransfer::OnExchangeClosing(Messaging::ExchangeContext * exchangeContext) +{ + mExchangeCtx = nullptr; +} + +CHIP_ERROR BdxTransfer::SendMessage(TransferSession::OutputEvent & event) +{ + VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); + + ::chip::Messaging::SendFlags sendFlags; + if (!event.msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport) && + !event.msgTypeData.HasMessageType(MessageType::BlockAckEOF)) + { + sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse); + } + return mExchangeCtx->SendMessage(event.msgTypeData.ProtocolId, event.msgTypeData.MessageType, event.MsgData.Retain(), + sendFlags); +} + +CHIP_ERROR BdxTransfer::SendBlock() +{ + VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE); + + size_t dataRemaining = mDataCount - mDataTransferredCount; + TransferSession::BlockData block; + block.Data = mData.data() + mDataTransferredCount; + block.Length = std::min(mTransfer.GetTransferBlockSize(), dataRemaining); + block.IsEof = block.Length == dataRemaining; + ReturnErrorOnFailure(mTransfer.PrepareBlock(block)); + mDataTransferredCount += block.Length; + ScheduleImmediatePoll(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR BdxTransfer::OnMessageReceived(chip::Messaging::ExchangeContext * exchangeContext, + const chip::PayloadHeader & payloadHeader, chip::System::PacketBufferHandle && payload) +{ + bool has_send_init = payloadHeader.HasMessageType(MessageType::SendInit); + bool has_receive_init = payloadHeader.HasMessageType(MessageType::ReceiveInit); + if (has_send_init || has_receive_init) + { + FabricIndex fabricIndex = exchangeContext->GetSessionHandle()->GetFabricIndex(); + NodeId peerNodeId = exchangeContext->GetSessionHandle()->GetPeer().GetNodeId(); + VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(peerNodeId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT); + + TransferControlFlags flags; + TransferRole role; + if (has_send_init) + { + flags = TransferControlFlags::kSenderDrive; + role = TransferRole::kReceiver; + } + else + { + flags = TransferControlFlags::kReceiverDrive; + role = TransferRole::kSender; + } + ReturnLogErrorOnFailure( + Responder::PrepareForTransfer(mSystemLayer, role, flags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollInterval)); + } + + return Responder::OnMessageReceived(exchangeContext, payloadHeader, std::move(payload)); +} + +} // namespace bdx +} // namespace chip diff --git a/src/controller/python/chip/bdx/bdx-transfer.h b/src/controller/python/chip/bdx/bdx-transfer.h new file mode 100644 index 0000000000..3ddf849d8c --- /dev/null +++ b/src/controller/python/chip/bdx/bdx-transfer.h @@ -0,0 +1,90 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#include + +#include +#include + +#include +#include + +#pragma once + +namespace chip { +namespace bdx { + +// A class that represents a BDX transfer initiated by the other end of the transfer. This implements most of the transfer, +// but uses a delegate for transfer control and data handling. The delegate must call one of ReceiveData, SendData, or Reject +// after or during a call to InitMessageReceived. +class BdxTransfer : public Responder +{ +public: + // The delegate is informed when specific events occur during the transfer. + class Delegate + { + public: + virtual ~Delegate() = default; + + // Called when the SendInit or ReceiveInit message is received. + virtual void InitMessageReceived(BdxTransfer * transfer, TransferSession::TransferInitData init_data) = 0; + // Called when a data block arrives. This is only used when the transfer is sending data to this controller. + virtual void DataReceived(BdxTransfer * transfer, const ByteSpan & block) = 0; + // Called when the transfer completes. The outcome of the transfer (successful or otherwise) is indicated by result. + virtual void TransferCompleted(BdxTransfer * transfer, CHIP_ERROR result) = 0; + }; + + BdxTransfer(System::Layer * systemLayer) : mSystemLayer(systemLayer) {} + + ~BdxTransfer() override = default; + + // Accepts the transfer with the intent of receiving data. This will send an AcceptSend message to the other end of the + // transfer. When a block of data arrives the delegate is invoked with the block. + CHIP_ERROR AcceptAndReceiveData(); + + // Accepts the transfer with the intent of sending data. This will send an AcceptReceive message to the other end of the + // transfer. + CHIP_ERROR AcceptAndSendData(const ByteSpan & data_to_send); + + // Rejects the transfer. + CHIP_ERROR Reject(); + + void SetDelegate(Delegate * delegate); + + // Responder virtual method overrides. + void HandleTransferSessionOutput(TransferSession::OutputEvent & event) override; + void OnExchangeClosing(Messaging::ExchangeContext * exchangeContext) override; + CHIP_ERROR OnMessageReceived(chip::Messaging::ExchangeContext * exchangeContext, const chip::PayloadHeader & payloadHeader, + chip::System::PacketBufferHandle && payload) override; + +private: + void EndSession(CHIP_ERROR result); + CHIP_ERROR SendMessage(TransferSession::OutputEvent & event); + CHIP_ERROR SendBlock(); + + Delegate * mDelegate = nullptr; + bool mAwaitingAccept = false; + + System::Layer * mSystemLayer = nullptr; + + std::vector mData; + size_t mDataCount = 0; + size_t mDataTransferredCount = 0; +}; + +} // namespace bdx +} // namespace chip diff --git a/src/controller/python/chip/bdx/bdx.cpp b/src/controller/python/chip/bdx/bdx.cpp new file mode 100644 index 0000000000..1d466df062 --- /dev/null +++ b/src/controller/python/chip/bdx/bdx.cpp @@ -0,0 +1,263 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +// The BDX transfer system is split into: +// * BdxTransfer: A transfer object that contains the information about a transfer and is an ExchangeDelegate. +// It owns the data for a transfer, either copying what was sent from Python or requiring the Python side to +// copy it during a callback. +// * TransferMap: A map that associates the BdxTransfer object with its Python context using TransferInfo objects. +// It owns the TransferInfo objects but doesn't own the BdxTransfer objects or the Python context objects. +// * TransferDelegate: A delegate that calls back into Python when certain events happen in C++. It uses the +// TransferMap but doesn't own it. +// TestBdxTransferServer: A server that listens for incoming BDX messages, creates BdxTransfer objects, and +// informs the delegate when certain events happen. It owns the BdxTransfer objects but not the delegate. A +// BdxTransfer object is created when a BDX message is received and destroyed when the transfer completes or +// fails. +// The TransferMap, TransferDelegate, and TestBdxTransferServer instances are all owned by this file. + +using PyObject = void *; + +namespace chip { +namespace python { + +// The Python callbacks to call when certain events happen. +using OnTransferObtainedCallback = void (*)(PyObject context, void * bdxTransfer, bdx::TransferControlFlags transferControlFlags, + uint16_t maxBlockSize, uint64_t startOffset, uint64_t length, + const uint8_t * fileDesignator, uint16_t fileDesignatorLength, const uint8_t * metadata, + size_t metadataLength); +using OnFailedToObtainTransferCallback = void (*)(PyObject context, PyChipError result); +using OnDataReceivedCallback = void (*)(PyObject context, const uint8_t * dataBuffer, size_t bufferLength); +using OnTransferCompletedCallback = void (*)(PyObject context, PyChipError result); + +// The callback methods provided by python. +OnTransferObtainedCallback gOnTransferObtainedCallback = nullptr; +OnFailedToObtainTransferCallback gOnFailedToObtainTransferCallback = nullptr; +OnDataReceivedCallback gOnDataReceivedCallback = nullptr; +OnTransferCompletedCallback gOnTransferCompletedCallback = nullptr; + +// The information for a single transfer. +struct TransferInfo +{ + // The transfer object. Owned by the transfer server. + bdx::BdxTransfer * Transfer = nullptr; + // The contexts for different python callbacks. Owned by the python side. + PyObject OnTransferObtainedContext = nullptr; + PyObject OnDataReceivedContext = nullptr; + PyObject OnTransferCompletedContext = nullptr; + + bool operator==(const TransferInfo & other) const { return Transfer == other.Transfer; } +}; + +// The set of transfers. +class TransferMap +{ +public: + // Returns the transfer data associated with the given transfer. + TransferInfo * TransferInfoForTransfer(bdx::BdxTransfer * transfer) + { + std::vector::iterator result = std::find_if( + mTransfers.begin(), mTransfers.end(), [transfer](const TransferInfo & data) { return data.Transfer == transfer; }); + VerifyOrReturnValue(result != mTransfers.end(), nullptr); + return &*result; + } + + // Returns the transfer data that has the given context when a transfer is obtained. + TransferInfo * TransferInfoForTransferObtainedContext(PyObject transferObtainedContext) + { + std::vector::iterator result = + std::find_if(mTransfers.begin(), mTransfers.end(), [transferObtainedContext](const TransferInfo & data) { + return data.OnTransferObtainedContext == transferObtainedContext; + }); + VerifyOrReturnValue(result != mTransfers.end(), nullptr); + return &*result; + } + + // This returns the next transfer data that has no associated BdxTransfer. + TransferInfo * NextUnassociatedTransferInfo() + { + std::vector::iterator result = + std::find_if(mTransfers.begin(), mTransfers.end(), [](const TransferInfo & data) { return data.Transfer == nullptr; }); + VerifyOrReturnValue(result != mTransfers.end(), nullptr); + return &*result; + } + + // Creates a new transfer data. + TransferInfo * CreateUnassociatedTransferInfo() { return &mTransfers.emplace_back(); } + + void RemoveTransferInfo(TransferInfo * transferInfo) + { + std::vector::iterator result = std::find(mTransfers.begin(), mTransfers.end(), *transferInfo); + VerifyOrReturn(result != mTransfers.end()); + mTransfers.erase(result); + } + +private: + std::vector mTransfers; +}; + +// A method to release a transfer. +void ReleaseTransfer(System::Layer * systemLayer, bdx::BdxTransfer * transfer); + +// A delegate to forward events from a transfer to the appropriate Python callback and context. +class TransferDelegate : public bdx::BdxTransfer::Delegate +{ +public: + TransferDelegate(TransferMap * transfers) : mTransfers(transfers) {} + ~TransferDelegate() override = default; + + void Init(System::Layer * systemLayer) { mSystemLayer = systemLayer; } + + void InitMessageReceived(bdx::BdxTransfer * transfer, bdx::TransferSession::TransferInitData init_data) override + { + TransferInfo * transferInfo = mTransfers->NextUnassociatedTransferInfo(); + if (gOnTransferObtainedCallback && transferInfo) + { + transferInfo->Transfer = transfer; + gOnTransferObtainedCallback(transferInfo->OnTransferObtainedContext, transfer, init_data.TransferCtlFlags, + init_data.MaxBlockSize, init_data.StartOffset, init_data.Length, init_data.FileDesignator, + init_data.FileDesLength, init_data.Metadata, init_data.MetadataLength); + } + } + + void DataReceived(bdx::BdxTransfer * transfer, const ByteSpan & block) override + { + TransferInfo * transferInfo = mTransfers->TransferInfoForTransfer(transfer); + if (gOnDataReceivedCallback && transferInfo) + { + gOnDataReceivedCallback(transferInfo->OnDataReceivedContext, block.data(), block.size()); + } + } + + void TransferCompleted(bdx::BdxTransfer * transfer, CHIP_ERROR result) override + { + TransferInfo * transferInfo = mTransfers->TransferInfoForTransfer(transfer); + if (!transferInfo && result != CHIP_NO_ERROR) + { + // The transfer failed during initialisation. + transferInfo = mTransfers->NextUnassociatedTransferInfo(); + if (gOnFailedToObtainTransferCallback && transferInfo) + { + gOnFailedToObtainTransferCallback(transferInfo->OnTransferObtainedContext, ToPyChipError(result)); + } + } + else if (gOnTransferCompletedCallback && transferInfo) + { + gOnTransferCompletedCallback(transferInfo->OnTransferCompletedContext, ToPyChipError(result)); + mTransfers->RemoveTransferInfo(transferInfo); + } + ReleaseTransfer(mSystemLayer, transfer); + } + +private: + TransferMap * mTransfers = nullptr; + System::Layer * mSystemLayer = nullptr; +}; + +TransferMap gTransfers; +TransferDelegate gBdxTransferDelegate(&gTransfers); +bdx::TestBdxTransferServer gBdxTransferServer(&gBdxTransferDelegate); + +void ReleaseTransfer(System::Layer * systemLayer, bdx::BdxTransfer * transfer) +{ + systemLayer->ScheduleWork( + [](auto * theSystemLayer, auto * appState) -> void { + auto * theTransfer = static_cast(appState); + gBdxTransferServer.Release(theTransfer); + }, + transfer); +} + +} // namespace python +} // namespace chip + +using namespace chip::python; + +// These methods are expected to be called from Python. +extern "C" { + +// Initialises the BDX system. +void pychip_Bdx_InitCallbacks(OnTransferObtainedCallback onTransferObtainedCallback, + OnFailedToObtainTransferCallback onFailedToObtainTransferCallback, + OnDataReceivedCallback onDataReceivedCallback, + OnTransferCompletedCallback onTransferCompletedCallback) +{ + gOnTransferObtainedCallback = onTransferObtainedCallback; + gOnFailedToObtainTransferCallback = onFailedToObtainTransferCallback; + gOnDataReceivedCallback = onDataReceivedCallback; + gOnTransferCompletedCallback = onTransferCompletedCallback; + chip::Controller::DeviceControllerFactory & factory = chip::Controller::DeviceControllerFactory::GetInstance(); + chip::System::Layer * systemLayer = factory.GetSystemState()->SystemLayer(); + gBdxTransferDelegate.Init(systemLayer); + gBdxTransferServer.Init(systemLayer, factory.GetSystemState()->ExchangeMgr()); +} + +// Prepares the BDX system to expect a new transfer. +PyChipError pychip_Bdx_ExpectBdxTransfer(PyObject transferObtainedContext) +{ + TransferInfo * transferInfo = gTransfers.CreateUnassociatedTransferInfo(); + VerifyOrReturnValue(transferInfo != nullptr, ToPyChipError(CHIP_ERROR_NO_MEMORY)); + transferInfo->OnTransferObtainedContext = transferObtainedContext; + gBdxTransferServer.ExpectATransfer(); + return ToPyChipError(CHIP_NO_ERROR); +} + +// Stops expecting a transfer. +PyChipError pychip_Bdx_StopExpectingBdxTransfer(PyObject transferObtainedContext) +{ + TransferInfo * transferInfo = gTransfers.TransferInfoForTransferObtainedContext(transferObtainedContext); + VerifyOrReturnValue(transferInfo != nullptr, ToPyChipError(CHIP_ERROR_NOT_FOUND)); + gBdxTransferServer.StopExpectingATransfer(); + gTransfers.RemoveTransferInfo(transferInfo); + return ToPyChipError(CHIP_NO_ERROR); +} + +// Accepts a transfer with the intent to receive data from the other device. +PyChipError pychip_Bdx_AcceptTransferAndReceiveData(chip::bdx::BdxTransfer * transfer, PyObject dataReceivedContext, + PyObject transferCompletedContext) +{ + TransferInfo * transferInfo = gTransfers.TransferInfoForTransfer(transfer); + transferInfo->OnDataReceivedContext = dataReceivedContext; + transferInfo->OnTransferCompletedContext = transferCompletedContext; + return ToPyChipError(transfer->AcceptAndReceiveData()); +} + +// Accepts a transfer with the intent to send data to the other device. +PyChipError pychip_Bdx_AcceptTransferAndSendData(chip::bdx::BdxTransfer * transfer, const uint8_t * dataBuffer, size_t dataLength, + PyObject transferCompletedContext) +{ + TransferInfo * transferInfo = gTransfers.TransferInfoForTransfer(transfer); + transferInfo->OnTransferCompletedContext = transferCompletedContext; + chip::ByteSpan data(dataBuffer, dataLength); + return ToPyChipError(transfer->AcceptAndSendData(data)); +} + +// Rejects a transfer. +PyChipError pychip_Bdx_RejectTransfer(chip::bdx::BdxTransfer * transfer) +{ + return ToPyChipError(transfer->Reject()); +} +} diff --git a/src/controller/python/chip/bdx/test-bdx-transfer-server.cpp b/src/controller/python/chip/bdx/test-bdx-transfer-server.cpp new file mode 100644 index 0000000000..86a0c9b9fb --- /dev/null +++ b/src/controller/python/chip/bdx/test-bdx-transfer-server.cpp @@ -0,0 +1,95 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#include + +namespace chip { +namespace bdx { + +TestBdxTransferServer::TestBdxTransferServer(BdxTransfer::Delegate * bdxTransferDelegate) : + mBdxTransferDelegate(bdxTransferDelegate) +{} + +TestBdxTransferServer::~TestBdxTransferServer() +{ + mTransferPool.ReleaseAll(); +} + +CHIP_ERROR TestBdxTransferServer::Init(System::Layer * systemLayer, Messaging::ExchangeManager * exchangeManager) +{ + VerifyOrReturnError(systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + mSystemLayer = systemLayer; + mExchangeManager = exchangeManager; + // This removes the BdxTransferServer registered as part of CHIPDeviceControllerFactory. + mExchangeManager->UnregisterUnsolicitedMessageHandlerForType(MessageType::SendInit); + return mExchangeManager->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id, this); +} + +void TestBdxTransferServer::Shutdown() +{ + VerifyOrReturn(mExchangeManager != nullptr); + LogErrorOnFailure(mExchangeManager->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::BDX::Id)); + mExchangeManager = nullptr; +} + +void TestBdxTransferServer::ExpectATransfer() +{ + ++mExpectedTransfers; +} + +void TestBdxTransferServer::StopExpectingATransfer() +{ + if (mExpectedTransfers > 0) + { + --mExpectedTransfers; + } +} + +void TestBdxTransferServer::Release(BdxTransfer * bdxTransfer) +{ + mTransferPool.ReleaseObject(bdxTransfer); +} + +CHIP_ERROR TestBdxTransferServer::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, + Messaging::ExchangeDelegate *& delegate) +{ + VerifyOrReturnValue(mExpectedTransfers != 0, CHIP_ERROR_HANDLER_NOT_SET); + + BdxTransfer * transfer = mTransferPool.CreateObject(mSystemLayer); + if (transfer == nullptr) + { + ChipLogError(BDX, "Failed to allocate BDX transfer. The pool (size %d) is exhausted.", static_cast(kTransferPoolSize)); + return CHIP_ERROR_NO_MEMORY; + } + transfer->SetDelegate(mBdxTransferDelegate); + delegate = transfer; + + --mExpectedTransfers; + + return CHIP_NO_ERROR; +} + +void TestBdxTransferServer::OnExchangeCreationFailed(Messaging::ExchangeDelegate * delegate) +{ + BdxTransfer * bdxTransfer = static_cast(delegate); + mBdxTransferDelegate->TransferCompleted(bdxTransfer, CHIP_ERROR_CONNECTION_ABORTED); + Release(bdxTransfer); +} + +} // namespace bdx +} // namespace chip diff --git a/src/controller/python/chip/bdx/test-bdx-transfer-server.h b/src/controller/python/chip/bdx/test-bdx-transfer-server.h new file mode 100644 index 0000000000..7caa298fae --- /dev/null +++ b/src/controller/python/chip/bdx/test-bdx-transfer-server.h @@ -0,0 +1,69 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace chip { +namespace bdx { + +// This class handles unsolicited BDX messages. It keeps track of the number of expect transfers, and will only allocate +// BdxTransfer objects if a transfer is expected. +// +// The controller must inform this manager when a transfer is expected: +// bdxTransferServer->ExpectATransfer(); +// At which point the next unsolicited BDX init message will allocate a BdxTransfer object. +class TestBdxTransferServer : public Messaging::UnsolicitedMessageHandler +{ +public: + TestBdxTransferServer(BdxTransfer::Delegate * bdxTransferDelegate); + ~TestBdxTransferServer() override; + + CHIP_ERROR Init(System::Layer * systemLayer, Messaging::ExchangeManager * exchangeManager); + void Shutdown(); + + // These keep track of the number of expected transfers. A transfer must be expected before this will allocate a + // BdxTransfer object. + void ExpectATransfer(); + void StopExpectingATransfer(); + + void Release(BdxTransfer * bdxTransfer); + + CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, Messaging::ExchangeDelegate *& delegate) override; + void OnExchangeCreationFailed(Messaging::ExchangeDelegate * delegate) override; + +private: + // The maximum number of transfers to support at once. This number was chosen because it should be sufficient for + // current tests that use BDX. + static constexpr size_t kTransferPoolSize = 2; + + ObjectPool mTransferPool; + System::Layer * mSystemLayer = nullptr; + Messaging::ExchangeManager * mExchangeManager = nullptr; + BdxTransfer::Delegate * mBdxTransferDelegate = nullptr; + size_t mExpectedTransfers = 0; +}; + +} // namespace bdx +} // namespace chip diff --git a/src/python_testing/TestBdxTransfer.py b/src/python_testing/TestBdxTransfer.py new file mode 100644 index 0000000000..bd173103bf --- /dev/null +++ b/src/python_testing/TestBdxTransfer.py @@ -0,0 +1,119 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# + +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: > +# --discriminator 1234 +# --KVS kvs1 +# --trace-to json:${TRACE_APP}.json +# --end_user_support_log /tmp/eusl.txt +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: false +# === END CI TEST ARGUMENTS === + +import asyncio +import random + +import chip.clusters as Clusters +from chip.bdx import BdxProtocol, BdxTransfer +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TestBdxTransfer(MatterBaseTest): + def desc_bdx_transfer(self) -> str: + return "Test a BDX transfer with the diagnostic logs cluster" + + def steps_bdx_transfer(self) -> list[TestStep]: + steps = [ + TestStep(1, "Generate the diagnostic log file."), + TestStep(2, "Set up the system to receive a BDX transfer."), + TestStep(3, "Send the command to request logs."), + TestStep(4, "Wait for the command's response or a BDX transfer."), + TestStep(5, "Verify the init message's parameters."), + TestStep(6, "Accept the transfer and obtain the data."), + TestStep(7, "Verify the obtained data."), + TestStep(8, "Check the command's response."), + ] + return steps + + @async_test_body + async def test_bdx_transfer(self): + self.step(1) + expected_data = random.randbytes(9240) + diagnostic_file = open("/tmp/eusl.txt", "wb") + diagnostic_file.write(expected_data) + diagnostic_file.close() + + self.step(2) + bdx_future: asyncio.futures.Future = self.default_controller.TestOnlyPrepareToReceiveBdxData() + + self.step(3) + file_designator = "filename" + command: Clusters.DiagnosticLogs.Commands.RetrieveLogsRequest = Clusters.DiagnosticLogs.Commands.RetrieveLogsRequest( + intent=Clusters.DiagnosticLogs.Enums.IntentEnum.kEndUserSupport, + requestedProtocol=Clusters.DiagnosticLogs.Enums.TransferProtocolEnum.kBdx, + transferFileDesignator=file_designator + ) + command_send_future = asyncio.create_task(self.default_controller.SendCommand( + self.dut_node_id, + 0, + command, + responseType=Clusters.DiagnosticLogs.Commands.RetrieveLogsResponse) + ) + + self.step(4) + done, pending = await asyncio.wait([command_send_future, bdx_future], return_when=asyncio.FIRST_COMPLETED) + + self.step(5) + asserts.assert_true(bdx_future in done, "BDX transfer didn't start") + bdx_transfer: BdxTransfer.BdxTransfer = bdx_future.result() + asserts.assert_equal(bdx_transfer.init_message.TransferControlFlags, + BdxProtocol.SENDER_DRIVE, "Invalid transfer control flags") + asserts.assert_equal(bdx_transfer.init_message.MaxBlockSize, 1024, "Invalid max block size") + asserts.assert_equal(bdx_transfer.init_message.StartOffset, 0, "Invalid start offset") + asserts.assert_equal(bdx_transfer.init_message.FileDesignator, + bytes(file_designator, encoding='utf8'), + "Invalid file designator") + + self.step(6) + data = await bdx_transfer.accept_and_receive_data() + + self.step(7) + asserts.assert_equal(data, expected_data, "Transferred data doesn't match") + + self.step(8) + command_response: Clusters.DiagnosticLogs.Commands.RetrieveLogsResponse + if command_send_future in done: + command_response = command_send_future.result() + else: + command_response = await command_send_future + asserts.assert_equal(command_response.status, Clusters.DiagnosticLogs.Enums.StatusEnum.kSuccess, "Invalid command response") + + +if __name__ == "__main__": + default_matter_test_main() From 9816fbec1a8451d80cab8bb6eaf780e7a282bc17 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Mon, 25 Nov 2024 12:00:59 -0800 Subject: [PATCH 087/219] [Fabric-Sync] Fix segment fault during fabric admin initialization (#36635) --- examples/fabric-sync/admin/FabricAdmin.cpp | 11 ----------- examples/fabric-sync/admin/FabricAdmin.h | 7 +++---- examples/fabric-sync/main.cpp | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index b4be20e0e2..3e96af42af 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -35,15 +35,6 @@ FabricAdmin FabricAdmin::sInstance; app::DefaultICDClientStorage FabricAdmin::sICDClientStorage; app::CheckInHandler FabricAdmin::sCheckInHandler; -FabricAdmin & FabricAdmin::Instance() -{ - if (!sInstance.mInitialized) - { - VerifyOrDie(sInstance.Init() == CHIP_NO_ERROR); - } - return sInstance; -} - CHIP_ERROR FabricAdmin::Init() { IcdManager::Instance().SetDelegate(&sInstance); @@ -56,8 +47,6 @@ CHIP_ERROR FabricAdmin::Init() ReturnLogErrorOnFailure(sCheckInHandler.Init(Controller::DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), &sICDClientStorage, &IcdManager::Instance(), engine)); - mInitialized = true; - return CHIP_NO_ERROR; } diff --git a/examples/fabric-sync/admin/FabricAdmin.h b/examples/fabric-sync/admin/FabricAdmin.h index 85547373f1..f906965a70 100644 --- a/examples/fabric-sync/admin/FabricAdmin.h +++ b/examples/fabric-sync/admin/FabricAdmin.h @@ -45,9 +45,11 @@ struct ScopedNodeIdHasher class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDelegate, public IcdManager::Delegate { public: - static FabricAdmin & Instance(); + static FabricAdmin & Instance() { return sInstance; } static chip::app::DefaultICDClientStorage & GetDefaultICDClientStorage() { return sICDClientStorage; } + CHIP_ERROR Init(); + CHIP_ERROR OpenCommissioningWindow(chip::Controller::CommissioningWindowVerifierParams params, chip::FabricIndex fabricIndex) override; @@ -100,10 +102,7 @@ class FabricAdmin final : public bridge::FabricAdminDelegate, public PairingDele static chip::app::DefaultICDClientStorage sICDClientStorage; static chip::app::CheckInHandler sCheckInHandler; - bool mInitialized = false; chip::NodeId mNodeId = chip::kUndefinedNodeId; - - CHIP_ERROR Init(); }; } // namespace admin diff --git a/examples/fabric-sync/main.cpp b/examples/fabric-sync/main.cpp index a372760d3a..1cad0d4965 100644 --- a/examples/fabric-sync/main.cpp +++ b/examples/fabric-sync/main.cpp @@ -110,16 +110,26 @@ int main(int argc, char * argv[]) Shell::RegisterCommands(); #endif - CHIP_ERROR err = admin::PairingManager::Instance().Init(GetDeviceCommissioner()); + ChipLinuxAppMainLoop(); + + CHIP_ERROR err = admin::FabricAdmin::Instance().Init(); + if (err != CHIP_NO_ERROR) { - ChipLogProgress(NotSpecified, "Failed to init PairingManager: %s ", ErrorStr(err)); + ChipLogProgress(NotSpecified, "Failed to init FabricAdmin: %s ", ErrorStr(err)); // End the program with non zero error code to indicate a error. return 1; } - ChipLinuxAppMainLoop(); + err = admin::PairingManager::Instance().Init(GetDeviceCommissioner()); + if (err != CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Failed to init PairingManager: %s ", ErrorStr(err)); + + // End the program with non zero error code to indicate a error. + return 1; + } return 0; } From 926ab430801b4158a8d75b1daf1b1adccf230639 Mon Sep 17 00:00:00 2001 From: Jake Ororke Date: Mon, 25 Nov 2024 14:16:57 -0800 Subject: [PATCH 088/219] [Implementation] Adding get_endpoint functionality to matter_testing support module (#36568) * Incorporating new get_endpoint functionality in matter_testing support module: - Added prior previous get_endpoint functionality from Cecille back to matter_testing support module. - Updating test modules to use new get_endpoint functionality mentioned in issue: https://github.com/project-chip/matter-test-scripts/issues/416 * Restyled by autopep8 * Updated TC_OCC_3_2 to resolve linting errors --------- Co-authored-by: Restyled.io --- src/python_testing/TC_BOOLCFG_2_1.py | 2 +- src/python_testing/TC_BOOLCFG_3_1.py | 2 +- src/python_testing/TC_BOOLCFG_4_1.py | 2 +- src/python_testing/TC_BOOLCFG_4_2.py | 2 +- src/python_testing/TC_BOOLCFG_4_3.py | 2 +- src/python_testing/TC_BOOLCFG_4_4.py | 2 +- src/python_testing/TC_BOOLCFG_5_1.py | 2 +- src/python_testing/TC_BOOLCFG_5_2.py | 2 +- src/python_testing/TC_CADMIN_1_11.py | 2 +- src/python_testing/TC_DEM_2_10.py | 2 +- src/python_testing/TC_DEM_2_2.py | 2 +- src/python_testing/TC_DEM_2_4.py | 2 +- src/python_testing/TC_DGSW_2_1.py | 2 +- src/python_testing/TC_DRLK_2_13.py | 2 +- src/python_testing/TC_DRLK_2_9.py | 2 +- src/python_testing/TC_EEVSE_2_2.py | 2 +- src/python_testing/TC_EEVSE_2_3.py | 2 +- src/python_testing/TC_EEVSE_2_4.py | 2 +- src/python_testing/TC_EEVSE_2_5.py | 2 +- src/python_testing/TC_EEVSE_2_6.py | 2 +- src/python_testing/TC_EEVSE_Utils.py | 2 +- src/python_testing/TC_EWATERHTR_2_2.py | 2 +- src/python_testing/TC_EWATERHTR_2_3.py | 2 +- src/python_testing/TC_FAN_3_1.py | 2 +- src/python_testing/TC_FAN_3_2.py | 3 +-- src/python_testing/TC_FAN_3_3.py | 2 +- src/python_testing/TC_FAN_3_4.py | 2 +- src/python_testing/TC_FAN_3_5.py | 2 +- src/python_testing/TC_LVL_2_3.py | 2 +- src/python_testing/TC_MWOCTRL_2_1.py | 2 +- src/python_testing/TC_MWOCTRL_2_2.py | 2 +- src/python_testing/TC_MWOCTRL_2_4.py | 2 +- src/python_testing/TC_MWOM_1_2.py | 2 +- src/python_testing/TC_OCC_2_1.py | 2 +- src/python_testing/TC_OCC_2_2.py | 2 +- src/python_testing/TC_OCC_2_3.py | 2 +- src/python_testing/TC_OCC_3_1.py | 6 +++--- src/python_testing/TC_OCC_3_2.py | 4 ++-- src/python_testing/TC_OPSTATE_2_1.py | 2 +- src/python_testing/TC_OPSTATE_2_2.py | 2 +- src/python_testing/TC_OPSTATE_2_3.py | 2 +- src/python_testing/TC_OPSTATE_2_4.py | 2 +- src/python_testing/TC_OPSTATE_2_5.py | 2 +- src/python_testing/TC_OPSTATE_2_6.py | 2 +- src/python_testing/TC_OVENOPSTATE_2_1.py | 2 +- src/python_testing/TC_OVENOPSTATE_2_2.py | 2 +- src/python_testing/TC_OVENOPSTATE_2_3.py | 2 +- src/python_testing/TC_OVENOPSTATE_2_4.py | 2 +- src/python_testing/TC_OVENOPSTATE_2_5.py | 2 +- src/python_testing/TC_PS_2_3.py | 2 +- src/python_testing/TC_PWRTL_2_1.py | 2 +- src/python_testing/TC_RVCCLEANM_1_2.py | 2 +- src/python_testing/TC_RVCCLEANM_2_1.py | 2 +- src/python_testing/TC_RVCCLEANM_2_2.py | 2 +- src/python_testing/TC_RVCOPSTATE_2_1.py | 2 +- src/python_testing/TC_RVCOPSTATE_2_3.py | 2 +- src/python_testing/TC_RVCOPSTATE_2_4.py | 2 +- src/python_testing/TC_RVCRUNM_1_2.py | 2 +- src/python_testing/TC_RVCRUNM_2_1.py | 2 +- src/python_testing/TC_RVCRUNM_2_2.py | 2 +- src/python_testing/TC_SEAR_1_2.py | 2 +- src/python_testing/TC_SEAR_1_3.py | 2 +- src/python_testing/TC_SEAR_1_4.py | 2 +- src/python_testing/TC_SEAR_1_5.py | 2 +- src/python_testing/TC_SEAR_1_6.py | 2 +- src/python_testing/TC_SWTCH.py | 10 +++++----- src/python_testing/TC_TSTAT_4_2.py | 2 +- src/python_testing/TC_VALCC_2_1.py | 3 ++- src/python_testing/TC_VALCC_3_1.py | 3 ++- src/python_testing/TC_VALCC_3_2.py | 3 ++- src/python_testing/TC_VALCC_3_3.py | 3 ++- src/python_testing/TC_VALCC_3_4.py | 3 ++- src/python_testing/TC_VALCC_4_1.py | 3 ++- src/python_testing/TC_VALCC_4_2.py | 3 ++- src/python_testing/TC_VALCC_4_3.py | 3 ++- src/python_testing/TC_VALCC_4_4.py | 3 ++- src/python_testing/TC_VALCC_4_5.py | 3 ++- src/python_testing/TC_WHM_1_2.py | 2 +- src/python_testing/TC_WHM_2_1.py | 2 +- .../chip/testing/matter_testing.py | 15 +++++++++++---- 80 files changed, 107 insertions(+), 91 deletions(-) diff --git a/src/python_testing/TC_BOOLCFG_2_1.py b/src/python_testing/TC_BOOLCFG_2_1.py index 2456457ce2..6f7090c0d8 100644 --- a/src/python_testing/TC_BOOLCFG_2_1.py +++ b/src/python_testing/TC_BOOLCFG_2_1.py @@ -72,7 +72,7 @@ def pics_TC_BOOLCFG_2_1(self) -> list[str]: @async_test_body async def test_TC_BOOLCFG_2_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) all_alarm_mode_bitmap_bits = functools.reduce( ior, [b.value for b in Clusters.BooleanStateConfiguration.Bitmaps.AlarmModeBitmap]) all_sensor_fault_bitmap_bits = functools.reduce( diff --git a/src/python_testing/TC_BOOLCFG_3_1.py b/src/python_testing/TC_BOOLCFG_3_1.py index 8ed77f6ba8..e305c4a7c8 100644 --- a/src/python_testing/TC_BOOLCFG_3_1.py +++ b/src/python_testing/TC_BOOLCFG_3_1.py @@ -75,7 +75,7 @@ def pics_TC_BOOLCFG_3_1(self) -> list[str]: @async_test_body async def test_TC_BOOLCFG_3_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.BooleanStateConfiguration.Attributes diff --git a/src/python_testing/TC_BOOLCFG_4_1.py b/src/python_testing/TC_BOOLCFG_4_1.py index dfe6aac340..9d7a259547 100644 --- a/src/python_testing/TC_BOOLCFG_4_1.py +++ b/src/python_testing/TC_BOOLCFG_4_1.py @@ -67,7 +67,7 @@ def pics_TC_BOOLCFG_4_1(self) -> list[str]: @async_test_body async def test_TC_BOOLCFG_4_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.BooleanStateConfiguration.Attributes diff --git a/src/python_testing/TC_BOOLCFG_4_2.py b/src/python_testing/TC_BOOLCFG_4_2.py index 093e389dcf..53ebb9cbad 100644 --- a/src/python_testing/TC_BOOLCFG_4_2.py +++ b/src/python_testing/TC_BOOLCFG_4_2.py @@ -89,7 +89,7 @@ async def test_TC_BOOLCFG_4_2(self): "the --hex-arg flag as PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:, " "e.g. --hex-arg PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f") - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) enableKey = self.matter_test_config.global_test_params['PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY'] self.step(1) diff --git a/src/python_testing/TC_BOOLCFG_4_3.py b/src/python_testing/TC_BOOLCFG_4_3.py index 845d8e9d4a..f487326c77 100644 --- a/src/python_testing/TC_BOOLCFG_4_3.py +++ b/src/python_testing/TC_BOOLCFG_4_3.py @@ -101,7 +101,7 @@ async def test_TC_BOOLCFG_4_3(self): "the --hex-arg flag as PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:, " "e.g. --hex-arg PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f") - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) enableKey = self.matter_test_config.global_test_params['PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY'] self.step(1) diff --git a/src/python_testing/TC_BOOLCFG_4_4.py b/src/python_testing/TC_BOOLCFG_4_4.py index c585b14a84..eef4b7d21c 100644 --- a/src/python_testing/TC_BOOLCFG_4_4.py +++ b/src/python_testing/TC_BOOLCFG_4_4.py @@ -93,7 +93,7 @@ async def test_TC_BOOLCFG_4_4(self): "the --hex-arg flag as PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:, " "e.g. --hex-arg PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f") - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) enableKey = self.matter_test_config.global_test_params['PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY'] self.step(1) diff --git a/src/python_testing/TC_BOOLCFG_5_1.py b/src/python_testing/TC_BOOLCFG_5_1.py index ec31d8341b..fcb23017f8 100644 --- a/src/python_testing/TC_BOOLCFG_5_1.py +++ b/src/python_testing/TC_BOOLCFG_5_1.py @@ -88,7 +88,7 @@ async def test_TC_BOOLCFG_5_1(self): "the --hex-arg flag as PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:, " "e.g. --hex-arg PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f") - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) enableKey = self.matter_test_config.global_test_params['PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY'] self.step(1) diff --git a/src/python_testing/TC_BOOLCFG_5_2.py b/src/python_testing/TC_BOOLCFG_5_2.py index fd6b88370d..b790e006c7 100644 --- a/src/python_testing/TC_BOOLCFG_5_2.py +++ b/src/python_testing/TC_BOOLCFG_5_2.py @@ -87,7 +87,7 @@ async def test_TC_BOOLCFG_5_2(self): "the --hex-arg flag as PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:, " "e.g. --hex-arg PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY:000102030405060708090a0b0c0d0e0f") - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) enableKey = self.matter_test_config.global_test_params['PIXIT.BOOLCFG.TEST_EVENT_TRIGGER_KEY'] self.step(1) diff --git a/src/python_testing/TC_CADMIN_1_11.py b/src/python_testing/TC_CADMIN_1_11.py index cefd8b44a7..3c818bd3be 100644 --- a/src/python_testing/TC_CADMIN_1_11.py +++ b/src/python_testing/TC_CADMIN_1_11.py @@ -28,7 +28,7 @@ # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # --PICS src/app/tests/suites/certification/ci-pics-values # factory-reset: true -# quiet: false +# quiet: true # === END CI TEST ARGUMENTS === diff --git a/src/python_testing/TC_DEM_2_10.py b/src/python_testing/TC_DEM_2_10.py index 810efdbfa2..40f44d571e 100644 --- a/src/python_testing/TC_DEM_2_10.py +++ b/src/python_testing/TC_DEM_2_10.py @@ -162,7 +162,7 @@ async def test_TC_DEM_2_10(self): self.step("4") sub_handler = ClusterAttributeChangeAccumulator(Clusters.DeviceEnergyManagement) await sub_handler.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint, + self.get_endpoint(), min_interval_sec=0, max_interval_sec=10, keepSubscriptions=False) diff --git a/src/python_testing/TC_DEM_2_2.py b/src/python_testing/TC_DEM_2_2.py index 168417dd98..390a7e8b30 100644 --- a/src/python_testing/TC_DEM_2_2.py +++ b/src/python_testing/TC_DEM_2_2.py @@ -181,7 +181,7 @@ async def test_TC_DEM_2_2(self): events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint(default=1)) self.step("4") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_DEM_2_4.py b/src/python_testing/TC_DEM_2_4.py index 1b591cd438..6fc5178ee2 100644 --- a/src/python_testing/TC_DEM_2_4.py +++ b/src/python_testing/TC_DEM_2_4.py @@ -186,7 +186,7 @@ async def test_TC_DEM_2_4(self): events_callback = EventChangeCallback(Clusters.DeviceEnergyManagement) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("4") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_DGSW_2_1.py b/src/python_testing/TC_DGSW_2_1.py index 6338932725..efc2df95fb 100644 --- a/src/python_testing/TC_DGSW_2_1.py +++ b/src/python_testing/TC_DGSW_2_1.py @@ -74,7 +74,7 @@ def steps_TC_DGSW_2_1(self) -> list[TestStep]: @async_test_body async def test_TC_DGSW_2_1(self): - endpoint = self.user_params.get("endpoint", 0) + endpoint = self.get_endpoint(default=0) # STEP 1: Commission DUT (already done) self.step(1) diff --git a/src/python_testing/TC_DRLK_2_13.py b/src/python_testing/TC_DRLK_2_13.py index 809e278517..66c6b3313d 100644 --- a/src/python_testing/TC_DRLK_2_13.py +++ b/src/python_testing/TC_DRLK_2_13.py @@ -368,7 +368,7 @@ async def test_TC_DRLK_2_13(self): self.groupIdentifier = bytes.fromhex("89d085fc302ca53e279bfcdecdf3c4ad") self.groupResolvingKey = bytes.fromhex("89d0859bfcdecdf3c4adfc302ca53e27") self.common_cluster_endpoint = 0 - self.app_cluster_endpoint = self.matter_test_config.endpoint + self.app_cluster_endpoint = self.get_endpoint(default=1) self.alirouser = "AliroUser" self.alirocredentialissuerkey = bytes.fromhex( "047a4c882d753924cdf3779a3c84fec2debaa6f0b3084450878acc7ddcce7856ae57b1ebbe2561015103dd7474c2a183675378ec55f1e465ac3436bf3dd5ca54d4") diff --git a/src/python_testing/TC_DRLK_2_9.py b/src/python_testing/TC_DRLK_2_9.py index fb294b724f..904d844a3e 100644 --- a/src/python_testing/TC_DRLK_2_9.py +++ b/src/python_testing/TC_DRLK_2_9.py @@ -379,7 +379,7 @@ async def test_TC_DRLK_2_9(self): self.maxrfidcodelength = None self.minrfidcodelength = None - self.endpoint = self.user_params.get("endpoint", 1) + self.endpoint = self.get_endpoint(default=1) print("endpoint", self.endpoint) # Aliro Keys for setting Aliro configuration and credential diff --git a/src/python_testing/TC_EEVSE_2_2.py b/src/python_testing/TC_EEVSE_2_2.py index 144bfd82d3..f51ea308a1 100644 --- a/src/python_testing/TC_EEVSE_2_2.py +++ b/src/python_testing/TC_EEVSE_2_2.py @@ -172,7 +172,7 @@ async def test_TC_EEVSE_2_2(self): events_callback = EventChangeCallback(Clusters.EnergyEvse) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("2") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_EEVSE_2_3.py b/src/python_testing/TC_EEVSE_2_3.py index 54c5baa1a7..31083109e9 100644 --- a/src/python_testing/TC_EEVSE_2_3.py +++ b/src/python_testing/TC_EEVSE_2_3.py @@ -211,7 +211,7 @@ async def test_TC_EEVSE_2_3(self): events_callback = EventChangeCallback(Clusters.EnergyEvse) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("2") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_EEVSE_2_4.py b/src/python_testing/TC_EEVSE_2_4.py index 10355debd0..eb5c4a2bab 100644 --- a/src/python_testing/TC_EEVSE_2_4.py +++ b/src/python_testing/TC_EEVSE_2_4.py @@ -127,7 +127,7 @@ async def test_TC_EEVSE_2_4(self): events_callback = EventChangeCallback(Clusters.EnergyEvse) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("2") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_EEVSE_2_5.py b/src/python_testing/TC_EEVSE_2_5.py index 4571cfb363..aa415a9858 100644 --- a/src/python_testing/TC_EEVSE_2_5.py +++ b/src/python_testing/TC_EEVSE_2_5.py @@ -119,7 +119,7 @@ async def test_TC_EEVSE_2_5(self): events_callback = EventChangeCallback(Clusters.EnergyEvse) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("2") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_EEVSE_2_6.py b/src/python_testing/TC_EEVSE_2_6.py index d66ff60bf6..ec93eceef0 100644 --- a/src/python_testing/TC_EEVSE_2_6.py +++ b/src/python_testing/TC_EEVSE_2_6.py @@ -149,7 +149,7 @@ async def test_TC_EEVSE_2_6(self): events_callback = EventChangeCallback(Clusters.EnergyEvse) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("4") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_EEVSE_Utils.py b/src/python_testing/TC_EEVSE_Utils.py index 244d2e5730..733dfc3b36 100644 --- a/src/python_testing/TC_EEVSE_Utils.py +++ b/src/python_testing/TC_EEVSE_Utils.py @@ -59,7 +59,7 @@ async def get_supported_energy_evse_attributes(self, endpoint: int = None): async def write_user_max_charge(self, endpoint: int = None, user_max_charge: int = 0): if endpoint is None: - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint() result = await self.default_controller.WriteAttribute(self.dut_node_id, [(endpoint, Clusters.EnergyEvse.Attributes.UserMaximumChargeCurrent(user_max_charge))]) diff --git a/src/python_testing/TC_EWATERHTR_2_2.py b/src/python_testing/TC_EWATERHTR_2_2.py index 1bd7185b1f..2c639a7c71 100644 --- a/src/python_testing/TC_EWATERHTR_2_2.py +++ b/src/python_testing/TC_EWATERHTR_2_2.py @@ -213,7 +213,7 @@ async def test_TC_EWATERHTR_2_2(self): events_callback = EventChangeCallback(Clusters.WaterHeaterManagement) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("3") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_EWATERHTR_2_3.py b/src/python_testing/TC_EWATERHTR_2_3.py index 0f1c3deae6..8833a3c58a 100644 --- a/src/python_testing/TC_EWATERHTR_2_3.py +++ b/src/python_testing/TC_EWATERHTR_2_3.py @@ -166,7 +166,7 @@ async def test_TC_EWATERHTR_2_3(self): events_callback = EventChangeCallback(Clusters.WaterHeaterManagement) await events_callback.start(self.default_controller, self.dut_node_id, - self.matter_test_config.endpoint) + self.get_endpoint()) self.step("3") await self.check_test_event_triggers_enabled() diff --git a/src/python_testing/TC_FAN_3_1.py b/src/python_testing/TC_FAN_3_1.py index 483be894ba..cc1f28b788 100644 --- a/src/python_testing/TC_FAN_3_1.py +++ b/src/python_testing/TC_FAN_3_1.py @@ -73,7 +73,7 @@ def pics_TC_FAN_3_1(self) -> list[str]: @async_test_body async def test_TC_FAN_3_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.print_step(1, "Commissioning, already done") diff --git a/src/python_testing/TC_FAN_3_2.py b/src/python_testing/TC_FAN_3_2.py index 799510eeea..2966e62f12 100644 --- a/src/python_testing/TC_FAN_3_2.py +++ b/src/python_testing/TC_FAN_3_2.py @@ -72,8 +72,7 @@ async def test_TC_FAN_3_2(self): logger.info("Test skipped because PICS FAN.S.F00 is not set") return - endpoint = self.user_params.get("endpoint", 1) - + endpoint = self.get_endpoint(default=1) self.print_step(1, "Commissioning, already done") self.print_step(2, "Read from the DUT the SpeedSetting attribute and store") diff --git a/src/python_testing/TC_FAN_3_3.py b/src/python_testing/TC_FAN_3_3.py index 7a4dde3f6c..055b7db0f0 100644 --- a/src/python_testing/TC_FAN_3_3.py +++ b/src/python_testing/TC_FAN_3_3.py @@ -94,7 +94,7 @@ async def test_TC_FAN_3_3(self): self.skip_all_remaining_steps(1) return - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) diff --git a/src/python_testing/TC_FAN_3_4.py b/src/python_testing/TC_FAN_3_4.py index 989680ed6b..168314e682 100644 --- a/src/python_testing/TC_FAN_3_4.py +++ b/src/python_testing/TC_FAN_3_4.py @@ -94,7 +94,7 @@ async def test_TC_FAN_3_4(self): logger.info("Test skipped because PICS FAN.S.F03 is not set") return - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) diff --git a/src/python_testing/TC_FAN_3_5.py b/src/python_testing/TC_FAN_3_5.py index 26dfc3e52f..8c75d7e22c 100644 --- a/src/python_testing/TC_FAN_3_5.py +++ b/src/python_testing/TC_FAN_3_5.py @@ -86,7 +86,7 @@ async def test_TC_FAN_3_5(self): logger.info("Test skipped because PICS FAN.S.F04 is not set") return - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) # Part 1 diff --git a/src/python_testing/TC_LVL_2_3.py b/src/python_testing/TC_LVL_2_3.py index d120bb7169..9f22367779 100644 --- a/src/python_testing/TC_LVL_2_3.py +++ b/src/python_testing/TC_LVL_2_3.py @@ -131,7 +131,7 @@ async def test_TC_LVL_2_3(self): self.step(6) sub_handler = ClusterAttributeChangeAccumulator(lvl) - await sub_handler.start(self.default_controller, self.dut_node_id, self.matter_test_config.endpoint) + await sub_handler.start(self.default_controller, self.dut_node_id, self.get_endpoint()) self.step(7) cmd = lvl.Commands.MoveToLevelWithOnOff(level=max_level, transitionTime=100, optionsMask=0, optionsOverride=0) diff --git a/src/python_testing/TC_MWOCTRL_2_1.py b/src/python_testing/TC_MWOCTRL_2_1.py index 6f913578cb..ed72806dc1 100644 --- a/src/python_testing/TC_MWOCTRL_2_1.py +++ b/src/python_testing/TC_MWOCTRL_2_1.py @@ -107,7 +107,7 @@ def pics_TC_MWOCTRL_2_1(self) -> list[str]: @async_test_body async def test_TC_MWOCTRL_2_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.MicrowaveOvenControl.Attributes diff --git a/src/python_testing/TC_MWOCTRL_2_2.py b/src/python_testing/TC_MWOCTRL_2_2.py index 4559689640..626cecd5cb 100644 --- a/src/python_testing/TC_MWOCTRL_2_2.py +++ b/src/python_testing/TC_MWOCTRL_2_2.py @@ -106,7 +106,7 @@ def pics_TC_MWOCTRL_2_2(self) -> list[str]: @async_test_body async def test_TC_MWOCTRL_2_2(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.MicrowaveOvenControl.Attributes diff --git a/src/python_testing/TC_MWOCTRL_2_4.py b/src/python_testing/TC_MWOCTRL_2_4.py index e05c4a5bd5..feadc2621e 100644 --- a/src/python_testing/TC_MWOCTRL_2_4.py +++ b/src/python_testing/TC_MWOCTRL_2_4.py @@ -75,7 +75,7 @@ def pics_TC_MWOCTRL_2_4(self) -> list[str]: @async_test_body async def test_TC_MWOCTRL_2_4(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.MicrowaveOvenControl.Attributes diff --git a/src/python_testing/TC_MWOM_1_2.py b/src/python_testing/TC_MWOM_1_2.py index 5cad6ce013..c24398eda2 100644 --- a/src/python_testing/TC_MWOM_1_2.py +++ b/src/python_testing/TC_MWOM_1_2.py @@ -67,7 +67,7 @@ def pics_TC_MWOM_1_2(self) -> list[str]: @async_test_body async def test_TC_MWOM_1_2(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) attributes = Clusters.MicrowaveOvenMode.Attributes diff --git a/src/python_testing/TC_OCC_2_1.py b/src/python_testing/TC_OCC_2_1.py index d831d486d2..e1d47e8e5f 100644 --- a/src/python_testing/TC_OCC_2_1.py +++ b/src/python_testing/TC_OCC_2_1.py @@ -83,7 +83,7 @@ def pics_TC_OCC_2_1(self) -> list[str]: @async_test_body async def test_TC_OCC_2_1(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint() cluster = Clusters.Objects.OccupancySensing attributes = cluster.Attributes diff --git a/src/python_testing/TC_OCC_2_2.py b/src/python_testing/TC_OCC_2_2.py index afa2e3cd61..1ea03896f7 100644 --- a/src/python_testing/TC_OCC_2_2.py +++ b/src/python_testing/TC_OCC_2_2.py @@ -65,7 +65,7 @@ def pics_TC_OCC_2_2(self) -> list[str]: @async_test_body async def test_TC_OCC_2_2(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint() self.step(1) # Already done, immediately go to step 2 diff --git a/src/python_testing/TC_OCC_2_3.py b/src/python_testing/TC_OCC_2_3.py index 8d4b53f429..0f90c809c3 100644 --- a/src/python_testing/TC_OCC_2_3.py +++ b/src/python_testing/TC_OCC_2_3.py @@ -46,7 +46,7 @@ class TC_OCC_2_3(MatterBaseTest): async def read_occ_attribute_expect_success(self, attribute): cluster = Clusters.Objects.OccupancySensing - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() return await self.read_single_attribute_check_success(endpoint=endpoint_id, cluster=cluster, attribute=attribute) def desc_TC_OCC_2_3(self) -> str: diff --git a/src/python_testing/TC_OCC_3_1.py b/src/python_testing/TC_OCC_3_1.py index cce0a2f697..2d7fb0e2de 100644 --- a/src/python_testing/TC_OCC_3_1.py +++ b/src/python_testing/TC_OCC_3_1.py @@ -55,13 +55,13 @@ def setup_test(self): async def read_occ_attribute_expect_success(self, attribute): cluster = Clusters.Objects.OccupancySensing - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint() return await self.read_single_attribute_check_success(endpoint=endpoint, cluster=cluster, attribute=attribute) async def write_hold_time(self, hold_time: Optional[Any]) -> Status: dev_ctrl = self.default_controller node_id = self.dut_node_id - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint() cluster = Clusters.OccupancySensing write_result = await dev_ctrl.WriteAttribute(node_id, [(endpoint, cluster.Attributes.HoldTime(hold_time))]) @@ -144,7 +144,7 @@ async def test_TC_OCC_3_1(self): self.step(4) # Setup Occupancy attribute subscription here - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() node_id = self.dut_node_id dev_ctrl = self.default_controller attrib_listener = ClusterAttributeChangeAccumulator(cluster) diff --git a/src/python_testing/TC_OCC_3_2.py b/src/python_testing/TC_OCC_3_2.py index 3a5ca17069..9f41bd69bb 100644 --- a/src/python_testing/TC_OCC_3_2.py +++ b/src/python_testing/TC_OCC_3_2.py @@ -56,7 +56,7 @@ def setup_test(self): async def read_occ_attribute_expect_success(self, attribute): cluster = Clusters.Objects.OccupancySensing - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() return await self.read_single_attribute_check_success(endpoint=endpoint_id, cluster=cluster, attribute=attribute) def desc_TC_OCC_3_2(self) -> str: @@ -100,7 +100,7 @@ def write_to_app_pipe(self, command): @async_test_body async def test_TC_OCC_3_2(self): - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() node_id = self.dut_node_id dev_ctrl = self.default_controller diff --git a/src/python_testing/TC_OPSTATE_2_1.py b/src/python_testing/TC_OPSTATE_2_1.py index 060b71d85e..272f9fa9c4 100644 --- a/src/python_testing/TC_OPSTATE_2_1.py +++ b/src/python_testing/TC_OPSTATE_2_1.py @@ -60,7 +60,7 @@ def pics_TC_OPSTATE_2_1(self) -> list[str]: @async_test_body async def test_TC_OPSTATE_2_1(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_1(endpoint) diff --git a/src/python_testing/TC_OPSTATE_2_2.py b/src/python_testing/TC_OPSTATE_2_2.py index f0ed8f214d..b3e426ada5 100644 --- a/src/python_testing/TC_OPSTATE_2_2.py +++ b/src/python_testing/TC_OPSTATE_2_2.py @@ -62,7 +62,7 @@ def pics_TC_OPSTATE_2_2(self) -> list[str]: @async_test_body async def test_TC_OPSTATE_2_2(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_2(endpoint=endpoint) diff --git a/src/python_testing/TC_OPSTATE_2_3.py b/src/python_testing/TC_OPSTATE_2_3.py index d35aa6e61e..53d79eaa10 100644 --- a/src/python_testing/TC_OPSTATE_2_3.py +++ b/src/python_testing/TC_OPSTATE_2_3.py @@ -62,7 +62,7 @@ def pics_TC_OPSTATE_2_3(self) -> list[str]: @async_test_body async def test_TC_OPSTATE_2_3(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_3(endpoint=endpoint) diff --git a/src/python_testing/TC_OPSTATE_2_4.py b/src/python_testing/TC_OPSTATE_2_4.py index ec2c7c17da..24f1ee50eb 100644 --- a/src/python_testing/TC_OPSTATE_2_4.py +++ b/src/python_testing/TC_OPSTATE_2_4.py @@ -62,7 +62,7 @@ def pics_TC_OPSTATE_2_4(self) -> list[str]: @async_test_body async def test_TC_OPSTATE_2_4(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_4(endpoint=endpoint) diff --git a/src/python_testing/TC_OPSTATE_2_5.py b/src/python_testing/TC_OPSTATE_2_5.py index 89a2462a2b..3327ca42c3 100644 --- a/src/python_testing/TC_OPSTATE_2_5.py +++ b/src/python_testing/TC_OPSTATE_2_5.py @@ -62,7 +62,7 @@ def pics_TC_OPSTATE_2_5(self) -> list[str]: @async_test_body async def test_TC_OPSTATE_2_5(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_5(endpoint=endpoint) diff --git a/src/python_testing/TC_OPSTATE_2_6.py b/src/python_testing/TC_OPSTATE_2_6.py index 0b9e1ec3bb..c024ad9c08 100644 --- a/src/python_testing/TC_OPSTATE_2_6.py +++ b/src/python_testing/TC_OPSTATE_2_6.py @@ -62,7 +62,7 @@ def pics_TC_OPSTATE_2_6(self) -> list[str]: @async_test_body async def test_TC_OPSTATE_2_6(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_6(endpoint=endpoint) diff --git a/src/python_testing/TC_OVENOPSTATE_2_1.py b/src/python_testing/TC_OVENOPSTATE_2_1.py index d830a416c0..9d0eb4a98c 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_1.py +++ b/src/python_testing/TC_OVENOPSTATE_2_1.py @@ -61,7 +61,7 @@ def pics_TC_OVENOPSTATE_2_1(self) -> list[str]: @async_test_body async def test_TC_OVENOPSTATE_2_1(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_1(endpoint) diff --git a/src/python_testing/TC_OVENOPSTATE_2_2.py b/src/python_testing/TC_OVENOPSTATE_2_2.py index 55afad11be..7cf1049bad 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_2.py +++ b/src/python_testing/TC_OVENOPSTATE_2_2.py @@ -62,7 +62,7 @@ def pics_TC_OVENOPSTATE_2_2(self) -> list[str]: @async_test_body async def test_TC_OVENOPSTATE_2_2(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_2(endpoint=endpoint) diff --git a/src/python_testing/TC_OVENOPSTATE_2_3.py b/src/python_testing/TC_OVENOPSTATE_2_3.py index 329bceb1fb..2b9a77e9dd 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_3.py +++ b/src/python_testing/TC_OVENOPSTATE_2_3.py @@ -61,7 +61,7 @@ def pics_TC_OVENOPSTATE_2_3(self) -> list[str]: @async_test_body async def test_TC_OVENOPSTATE_2_3(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_3(endpoint=endpoint) diff --git a/src/python_testing/TC_OVENOPSTATE_2_4.py b/src/python_testing/TC_OVENOPSTATE_2_4.py index ffc639390e..667b9c734e 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_4.py +++ b/src/python_testing/TC_OVENOPSTATE_2_4.py @@ -61,7 +61,7 @@ def pics_TC_OVENOPSTATE_2_4(self) -> list[str]: @async_test_body async def test_TC_OVENOPSTATE_2_4(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_4(endpoint=endpoint) diff --git a/src/python_testing/TC_OVENOPSTATE_2_5.py b/src/python_testing/TC_OVENOPSTATE_2_5.py index 42edca72f3..cd52469c55 100644 --- a/src/python_testing/TC_OVENOPSTATE_2_5.py +++ b/src/python_testing/TC_OVENOPSTATE_2_5.py @@ -62,7 +62,7 @@ def pics_TC_OVENOPSTATE_2_5(self) -> list[str]: @async_test_body async def test_TC_OVENOPSTATE_2_5(self): - endpoint = self.matter_test_config.endpoint + endpoint = self.get_endpoint(default=1) await self.TEST_TC_OPSTATE_BASE_2_5(endpoint=endpoint) diff --git a/src/python_testing/TC_PS_2_3.py b/src/python_testing/TC_PS_2_3.py index 13f4420b0a..1ba65b47d6 100644 --- a/src/python_testing/TC_PS_2_3.py +++ b/src/python_testing/TC_PS_2_3.py @@ -62,7 +62,7 @@ async def test_TC_PS_2_3(self): self.step(2) ps = Clusters.PowerSource sub_handler = ClusterAttributeChangeAccumulator(ps) - await sub_handler.start(self.default_controller, self.dut_node_id, self.matter_test_config.endpoint) + await sub_handler.start(self.default_controller, self.dut_node_id, self.get_endpoint()) self.step(3) logging.info("This test will now wait for 30 seconds.") diff --git a/src/python_testing/TC_PWRTL_2_1.py b/src/python_testing/TC_PWRTL_2_1.py index 9d4b3de977..ff3a66a886 100644 --- a/src/python_testing/TC_PWRTL_2_1.py +++ b/src/python_testing/TC_PWRTL_2_1.py @@ -51,7 +51,7 @@ async def test_TC_PWRTL_2_1(self): attributes = Clusters.PowerTopology.Attributes - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) powertop_attr_list = Clusters.Objects.PowerTopology.Attributes.AttributeList powertop_cluster = Clusters.Objects.PowerTopology diff --git a/src/python_testing/TC_RVCCLEANM_1_2.py b/src/python_testing/TC_RVCCLEANM_1_2.py index 3dfd75f4f4..b755d72756 100644 --- a/src/python_testing/TC_RVCCLEANM_1_2.py +++ b/src/python_testing/TC_RVCCLEANM_1_2.py @@ -69,7 +69,7 @@ def pics_TC_RVCCLEANM_1_2(self) -> list[str]: @async_test_body async def test_TC_RVCCLEANM_1_2(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() attributes = Clusters.RvcCleanMode.Attributes diff --git a/src/python_testing/TC_RVCCLEANM_2_1.py b/src/python_testing/TC_RVCCLEANM_2_1.py index 5234a74685..5c5271e0be 100644 --- a/src/python_testing/TC_RVCCLEANM_2_1.py +++ b/src/python_testing/TC_RVCCLEANM_2_1.py @@ -88,7 +88,7 @@ async def test_TC_RVCCLEANM_2_1(self): "PIXIT.RVCCLEANM.MODE_CHANGE_FAIL must be included on the command line in " "the --int-arg flag as PIXIT.RVCCLEANM.MODE_CHANGE_FAIL:") - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() self.mode_ok = self.matter_test_config.global_test_params['PIXIT.RVCCLEANM.MODE_CHANGE_OK'] self.mode_fail = self.matter_test_config.global_test_params['PIXIT.RVCCLEANM.MODE_CHANGE_FAIL'] self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") diff --git a/src/python_testing/TC_RVCCLEANM_2_2.py b/src/python_testing/TC_RVCCLEANM_2_2.py index 7352d03e24..a34d0cda2a 100644 --- a/src/python_testing/TC_RVCCLEANM_2_2.py +++ b/src/python_testing/TC_RVCCLEANM_2_2.py @@ -105,7 +105,7 @@ def pics_TC_RVCCLEANM_2_2(self) -> list[str]: @async_test_body async def test_TC_RVCCLEANM_2_2(self): self.directmodech_bit_mask = Clusters.RvcCleanMode.Bitmaps.Feature.kDirectModeChange - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: app_pid = self.matter_test_config.app_pid diff --git a/src/python_testing/TC_RVCOPSTATE_2_1.py b/src/python_testing/TC_RVCOPSTATE_2_1.py index 48715c3b7a..428aa9a5ab 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_1.py +++ b/src/python_testing/TC_RVCOPSTATE_2_1.py @@ -85,7 +85,7 @@ def TC_RVCOPSTATE_2_1(self) -> list[str]: @async_test_body async def test_TC_RVCOPSTATE_2_1(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_RVCOPSTATE_2_3.py b/src/python_testing/TC_RVCOPSTATE_2_3.py index 1b522117b9..ce583a7f52 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_3.py +++ b/src/python_testing/TC_RVCOPSTATE_2_3.py @@ -158,7 +158,7 @@ def pics_TC_RVCOPSTATE_2_3(self) -> list[str]: @async_test_body async def test_TC_RVCOPSTATE_2_3(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_RVCOPSTATE_2_4.py b/src/python_testing/TC_RVCOPSTATE_2_4.py index ad515dbff1..c1bbb5509c 100644 --- a/src/python_testing/TC_RVCOPSTATE_2_4.py +++ b/src/python_testing/TC_RVCOPSTATE_2_4.py @@ -103,7 +103,7 @@ def pics_TC_RVCOPSTATE_2_4(self) -> list[str]: @async_test_body async def test_TC_RVCOPSTATE_2_4(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_RVCRUNM_1_2.py b/src/python_testing/TC_RVCRUNM_1_2.py index 90db1601b1..369df1ddc6 100644 --- a/src/python_testing/TC_RVCRUNM_1_2.py +++ b/src/python_testing/TC_RVCRUNM_1_2.py @@ -69,7 +69,7 @@ def pics_TC_RVCRUNM_1_2(self) -> list[str]: @async_test_body async def test_TC_RVCRUNM_1_2(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() attributes = Clusters.RvcRunMode.Attributes diff --git a/src/python_testing/TC_RVCRUNM_2_1.py b/src/python_testing/TC_RVCRUNM_2_1.py index 55c37c7094..802c87fad5 100644 --- a/src/python_testing/TC_RVCRUNM_2_1.py +++ b/src/python_testing/TC_RVCRUNM_2_1.py @@ -83,7 +83,7 @@ async def test_TC_RVCRUNM_2_1(self): "PIXIT.RVCRUNM.MODE_CHANGE_FAIL must be included on the command line in " "the --int-arg flag as PIXIT.RVCRUNM.MODE_CHANGE_FAIL:") - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() self.mode_ok = self.matter_test_config.global_test_params['PIXIT.RVCRUNM.MODE_CHANGE_OK'] self.mode_fail = self.matter_test_config.global_test_params['PIXIT.RVCRUNM.MODE_CHANGE_FAIL'] self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") diff --git a/src/python_testing/TC_RVCRUNM_2_2.py b/src/python_testing/TC_RVCRUNM_2_2.py index e78d6d7f42..55c5a6ef17 100644 --- a/src/python_testing/TC_RVCRUNM_2_2.py +++ b/src/python_testing/TC_RVCRUNM_2_2.py @@ -134,7 +134,7 @@ async def test_TC_RVCRUNM_2_2(self): "PIXIT.RVCRUNM.MODE_B:") self.directmodech_bit_mask = Clusters.RvcRunMode.Bitmaps.Feature.kDirectModeChange - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") self.mode_a = self.matter_test_config.global_test_params['PIXIT.RVCRUNM.MODE_A'] self.mode_b = self.matter_test_config.global_test_params['PIXIT.RVCRUNM.MODE_B'] diff --git a/src/python_testing/TC_SEAR_1_2.py b/src/python_testing/TC_SEAR_1_2.py index 41773804e4..039a2ff9d0 100644 --- a/src/python_testing/TC_SEAR_1_2.py +++ b/src/python_testing/TC_SEAR_1_2.py @@ -204,7 +204,7 @@ def TC_SEAR_1_2(self) -> list[str]: @async_test_body async def test_TC_SEAR_1_2(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint(default=1) asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_SEAR_1_3.py b/src/python_testing/TC_SEAR_1_3.py index 2c2b85a13c..50818c3c60 100644 --- a/src/python_testing/TC_SEAR_1_3.py +++ b/src/python_testing/TC_SEAR_1_3.py @@ -88,7 +88,7 @@ def TC_SEAR_1_3(self) -> list[str]: @async_test_body async def test_TC_SEAR_1_3(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_SEAR_1_4.py b/src/python_testing/TC_SEAR_1_4.py index cf53f446f9..704fd97a54 100644 --- a/src/python_testing/TC_SEAR_1_4.py +++ b/src/python_testing/TC_SEAR_1_4.py @@ -60,7 +60,7 @@ def TC_SEAR_1_4(self) -> list[str]: @async_test_body async def test_TC_SEAR_1_4(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_SEAR_1_5.py b/src/python_testing/TC_SEAR_1_5.py index 130ccb8d59..96209191e6 100644 --- a/src/python_testing/TC_SEAR_1_5.py +++ b/src/python_testing/TC_SEAR_1_5.py @@ -102,7 +102,7 @@ def TC_SEAR_1_5(self) -> list[str]: @async_test_body async def test_TC_SEAR_1_5(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_SEAR_1_6.py b/src/python_testing/TC_SEAR_1_6.py index dc6188a14e..6e5c2157d0 100644 --- a/src/python_testing/TC_SEAR_1_6.py +++ b/src/python_testing/TC_SEAR_1_6.py @@ -85,7 +85,7 @@ def TC_SEAR_1_6(self) -> list[str]: @async_test_body async def test_TC_SEAR_1_6(self): - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() asserts.assert_false(self.endpoint is None, "--endpoint must be included on the command line in.") self.is_ci = self.check_pics("PICS_SDK_CI_ONLY") if self.is_ci: diff --git a/src/python_testing/TC_SWTCH.py b/src/python_testing/TC_SWTCH.py index fe55013452..e59842b056 100644 --- a/src/python_testing/TC_SWTCH.py +++ b/src/python_testing/TC_SWTCH.py @@ -335,7 +335,7 @@ def steps_TC_SWTCH_2_2(self): async def test_TC_SWTCH_2_2(self): post_prompt_settle_delay_seconds = 10.0 cluster = Clusters.Switch - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() # Step 1: Commissioning - already done self.step(1) @@ -452,7 +452,7 @@ async def test_TC_SWTCH_2_3(self): has_msl_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchLongPress) != 0 has_as_feature = (feature_map & cluster.Bitmaps.Feature.kActionSwitch) != 0 - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() self.step(2) event_listener = EventChangeCallback(cluster) @@ -524,7 +524,7 @@ async def test_TC_SWTCH_2_4(self): switch_pressed_position = self._default_pressed_position post_prompt_settle_delay_seconds = 10.0 - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() cluster = Clusters.Objects.Switch # Step 1: Commission DUT - already done @@ -704,7 +704,7 @@ async def test_TC_SWTCH_2_5(self): has_msr_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchRelease) multi_press_max = await self.read_single_attribute_check_success(cluster, attribute=cluster.Attributes.MultiPressMax) - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() pressed_position = self._default_pressed_position self.step(2) @@ -882,7 +882,7 @@ async def test_TC_SWTCH_2_6(self): has_msl_feature = (feature_map & cluster.Bitmaps.Feature.kMomentarySwitchLongPress) multi_press_max = await self.read_single_attribute_check_success(cluster, attribute=cluster.Attributes.MultiPressMax) - endpoint_id = self.matter_test_config.endpoint + endpoint_id = self.get_endpoint() pressed_position = self._default_pressed_position self.step(2) diff --git a/src/python_testing/TC_TSTAT_4_2.py b/src/python_testing/TC_TSTAT_4_2.py index 85ff487a9d..1cdc54923e 100644 --- a/src/python_testing/TC_TSTAT_4_2.py +++ b/src/python_testing/TC_TSTAT_4_2.py @@ -253,7 +253,7 @@ def steps_TC_TSTAT_4_2(self) -> list[TestStep]: @ async_test_body async def test_TC_TSTAT_4_2(self): - endpoint = self.matter_test_config.endpoint if self.matter_test_config.endpoint is not None else 1 + endpoint = self.get_endpoint() self.step("1") # Commission DUT - already done diff --git a/src/python_testing/TC_VALCC_2_1.py b/src/python_testing/TC_VALCC_2_1.py index d6f00b00a6..c01d801b22 100644 --- a/src/python_testing/TC_VALCC_2_1.py +++ b/src/python_testing/TC_VALCC_2_1.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -74,7 +75,7 @@ def pics_TC_VALCC_2_1(self) -> list[str]: @async_test_body async def test_TC_VALCC_2_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_3_1.py b/src/python_testing/TC_VALCC_3_1.py index 4b53ab032c..5f3c58d0b9 100644 --- a/src/python_testing/TC_VALCC_3_1.py +++ b/src/python_testing/TC_VALCC_3_1.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -69,7 +70,7 @@ def pics_TC_VALCC_3_1(self) -> list[str]: @async_test_body async def test_TC_VALCC_3_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_3_2.py b/src/python_testing/TC_VALCC_3_2.py index 6905e3bde8..44dc320c0a 100644 --- a/src/python_testing/TC_VALCC_3_2.py +++ b/src/python_testing/TC_VALCC_3_2.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -71,7 +72,7 @@ def pics_TC_VALCC_3_2(self) -> list[str]: @async_test_body async def test_TC_VALCC_3_2(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_3_3.py b/src/python_testing/TC_VALCC_3_3.py index a63053cf34..97e29f9b1a 100644 --- a/src/python_testing/TC_VALCC_3_3.py +++ b/src/python_testing/TC_VALCC_3_3.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -72,7 +73,7 @@ def pics_TC_VALCC_3_3(self) -> list[str]: @async_test_body async def test_TC_VALCC_3_3(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_3_4.py b/src/python_testing/TC_VALCC_3_4.py index 30c57dcb3f..05782fabed 100644 --- a/src/python_testing/TC_VALCC_3_4.py +++ b/src/python_testing/TC_VALCC_3_4.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -67,7 +68,7 @@ def pics_TC_VALCC_3_4(self) -> list[str]: @async_test_body async def test_TC_VALCC_3_4(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_4_1.py b/src/python_testing/TC_VALCC_4_1.py index 9af428d103..f30df68d79 100644 --- a/src/python_testing/TC_VALCC_4_1.py +++ b/src/python_testing/TC_VALCC_4_1.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -71,7 +72,7 @@ def pics_TC_VALCC_4_1(self) -> list[str]: @async_test_body async def test_TC_VALCC_4_1(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_4_2.py b/src/python_testing/TC_VALCC_4_2.py index 9365e5bc78..3394df61ba 100644 --- a/src/python_testing/TC_VALCC_4_2.py +++ b/src/python_testing/TC_VALCC_4_2.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -74,7 +75,7 @@ def pics_TC_VALCC_4_2(self) -> list[str]: @async_test_body async def test_TC_VALCC_4_2(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_4_3.py b/src/python_testing/TC_VALCC_4_3.py index b0762d0d88..c43f9303d2 100644 --- a/src/python_testing/TC_VALCC_4_3.py +++ b/src/python_testing/TC_VALCC_4_3.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -71,7 +72,7 @@ def pics_TC_VALCC_4_3(self) -> list[str]: @async_test_body async def test_TC_VALCC_4_3(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_4_4.py b/src/python_testing/TC_VALCC_4_4.py index 63cc6170ab..8915bd9044 100644 --- a/src/python_testing/TC_VALCC_4_4.py +++ b/src/python_testing/TC_VALCC_4_4.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -80,7 +81,7 @@ def pics_TC_VALCC_4_4(self) -> list[str]: @async_test_body async def test_TC_VALCC_4_4(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_VALCC_4_5.py b/src/python_testing/TC_VALCC_4_5.py index c6b7674c6c..052e424529 100644 --- a/src/python_testing/TC_VALCC_4_5.py +++ b/src/python_testing/TC_VALCC_4_5.py @@ -27,6 +27,7 @@ # --passcode 20202021 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --endpoint 1 # factory-reset: true # quiet: true # === END CI TEST ARGUMENTS === @@ -71,7 +72,7 @@ def pics_TC_VALCC_4_5(self) -> list[str]: @async_test_body async def test_TC_VALCC_4_5(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) self.step(1) attributes = Clusters.ValveConfigurationAndControl.Attributes diff --git a/src/python_testing/TC_WHM_1_2.py b/src/python_testing/TC_WHM_1_2.py index 2bbcdd5108..0ce34ee831 100644 --- a/src/python_testing/TC_WHM_1_2.py +++ b/src/python_testing/TC_WHM_1_2.py @@ -71,7 +71,7 @@ def pics_TC_WHM_1_2(self) -> list[str]: @async_test_body async def test_TC_WHM_1_2(self): - endpoint = self.user_params.get("endpoint", 1) + endpoint = self.get_endpoint(default=1) attributes = Clusters.WaterHeaterMode.Attributes diff --git a/src/python_testing/TC_WHM_2_1.py b/src/python_testing/TC_WHM_2_1.py index 538450e598..7380c7a862 100644 --- a/src/python_testing/TC_WHM_2_1.py +++ b/src/python_testing/TC_WHM_2_1.py @@ -93,7 +93,7 @@ async def test_TC_WHM_2_1(self): ModeManual = 1 # ModeTimed = 2 - self.endpoint = self.matter_test_config.endpoint + self.endpoint = self.get_endpoint() attributes = Clusters.WaterHeaterMode.Attributes diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index 053fa575c6..bb3666f551 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -1087,6 +1087,9 @@ def certificate_authority_manager(self) -> chip.CertificateAuthority.Certificate def dut_node_id(self) -> int: return self.matter_test_config.dut_node_ids[0] + def get_endpoint(self, default: Optional[int] = 0) -> int: + return self.matter_test_config.endpoint if self.matter_test_config.endpoint is not None else default + def setup_class(self): super().setup_class() @@ -1163,7 +1166,8 @@ async def read_single_attribute_check_success( if node_id is None: node_id = self.dut_node_id if endpoint is None: - endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint + #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint + endpoint = self.get_endpoint() result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabric_filtered) attr_ret = result[endpoint][cluster][attribute] @@ -1195,7 +1199,8 @@ async def read_single_attribute_expect_error( if node_id is None: node_id = self.dut_node_id if endpoint is None: - endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint + #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint + endpoint = self.get_endpoint() result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabric_filtered) attr_ret = result[endpoint][cluster][attribute] @@ -1243,7 +1248,8 @@ async def send_single_cmd( if node_id is None: node_id = self.dut_node_id if endpoint is None: - endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint + #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint + endpoint = self.get_endpoint() result = await dev_ctrl.SendCommand(nodeid=node_id, endpoint=endpoint, payload=cmd, timedRequestTimeoutMs=timedRequestTimeoutMs, payloadCapability=payloadCapability) @@ -1836,7 +1842,8 @@ def convert_args_to_matter_config(args: argparse.Namespace) -> MatterTestConfig: config.pics = {} if args.PICS is None else read_pics_from_file(args.PICS) config.tests = [] if args.tests is None else args.tests config.timeout = args.timeout # This can be none, we pull the default from the test if it's unspecified - config.endpoint = args.endpoint + #config.endpoint = args.endpoint + config.endpoint = args.endpoint # This can be None, the get_endpoint function allows the tests to supply a default config.app_pid = 0 if args.app_pid is None else args.app_pid config.controller_node_id = args.controller_node_id From c53bbb134cb3589eb0a2d488d58ceaf3c7312b6c Mon Sep 17 00:00:00 2001 From: Gibran Vargas <131407127+gvargas-csa@users.noreply.github.com> Date: Mon, 25 Nov 2024 14:18:35 -0800 Subject: [PATCH 089/219] TC-OPCREDS-3.4: Automate (#33541) * chore(TC_OPCREDS_3.4): skeleton class * chore(TC_OPCREDS_3.4): implementation until step CSRRequest IsForUpdatedNOC=True * chore(TC_OPCREDS_3.4): All test step are implement using the old way to printed them * chore(TC_OPCREDS_3.4): patch from restyled code * chore(TC_OPCREDS_3.4): restyled by autopep8 * chore(TC_OPCREDS_3.4): fix code-lints * chore(TC_OPCREDS_3.4): add suggestions * chore(TC_OPCREDS_3.4): steps _method instead print each step and add suggestions * chore(TC_OPCREDS_3.4): fix restyled * chore(TC_OPCREDS_3.4): fix re-implementation validate single entry certs * chore(TC_OPCREDS_3.4): fix resyled * chore(TC_OPCREDS_3.4): reverting commissioningBuilingBlocks without icac and nocBytes * chore(TC_OPCREDS_3.4): fix matter_testing_support ModuleNotError * chore(TC_OPCREDS_3.4): added and replaced some outcomes/methods for TestSteps * chore(TC_OPCREDS_3.4): fix restyled * chore(TC_OPCREDS_3.4): fix restyled * chore(TC_OPCREDS_3.4): added suggestions * chore(TC_OPCREDS_3.4): added expected outcomes for some test step * chore(TC_OPCREDS_3.4): fix restyled * chore(TC_OPCREDS_3.4): fix f-strings without any placeholder * chore(TC_OPCREDS_3.4): implemented all expected outcomes for all steps * chore(TC_OPCREDS_3.4): fix restyled * Update src/python_testing/TC_OPCREDS_3_4.py Needs the PICS function Co-authored-by: C Freeman --------- Co-authored-by: C Freeman --- src/python_testing/TC_OPCREDS_3_4.py | 305 ++++++++++++++++++++++++ src/python_testing/test_plan_support.py | 8 + 2 files changed, 313 insertions(+) create mode 100644 src/python_testing/TC_OPCREDS_3_4.py diff --git a/src/python_testing/TC_OPCREDS_3_4.py b/src/python_testing/TC_OPCREDS_3_4.py new file mode 100644 index 0000000000..e2657ba160 --- /dev/null +++ b/src/python_testing/TC_OPCREDS_3_4.py @@ -0,0 +1,305 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# + +# See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments +# for details about the block below. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --PICS src/app/tests/suites/certification/ci-pics-values +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import chip.clusters as Clusters +from chip.interaction_model import InteractionModelError, Status +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts +from test_plan_support import commission_if_required, read_attribute, send_command + + +def verify_noc() -> str: + return ("- Verify that the returned list has a single entry.\n" + "- Save the NOC field as noc_original and the ICAC field as icac_original.\n") + + +def verify_trusted_root_original() -> str: + return ("Verify that the returned list has a single entry. Save the entry as trusted_root_original") + + +def verify_failsafe_status() -> str: + return ("Verify that the DUT responds with FAILSAFE_REQUIRED") + + +def verify_armfailsafe_response() -> str: + return ("Verify that DUT sends ArmFailSafeResponse with the ErrorCode set to OK") + + +def verify_noc_response(status) -> str: + return (f"Verify that the DUT responds with a NOCResponse with the StatusCode field set to {status}") + + +def verify_csr_not_update() -> str: + return ("Verify that the DUT returns a CSRResponse and save as csr_not_update") + + +def verify_constraint_error() -> str: + return ("Verify that the DUT responds with CONSTRAINT_ERROR") + + +def verify_csr_pase() -> str: + return ("Verify that the DUT returns a CSRResponse and save as csr_pase") + + +def verify_unsupported_access() -> str: + return ("Verify that the DUT responds with UNSUPPORTED_ACCESS") + + +class TC_OPCREDS_3_4(MatterBaseTest): + def desc_TC_OPCREDS_3_4(self): + return " UpdateNOC-Error Condition [DUT-Server]" + + def pics_OPCREDS_3_4(self): + return ['OPCREDS.S'] + + def steps_TC_OPCREDS_3_4(self): + return [TestStep(1, commission_if_required('TH1'), is_commissioning=True), + TestStep( + 2, f"TH1 {read_attribute('NOCs')} from the Node Operational Credentials cluster using a fabric-filtered read. Save the NOCs as nocs.", None, verify_noc()), + TestStep( + 3, f"TH1 {read_attribute('TrustedRootCertificates')} attribute from the Node Operational Credentials cluster", None, verify_trusted_root_original()), + TestStep( + 4, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster with the following fields: NOCValue and ICACValue", None, verify_failsafe_status()), + TestStep( + 5, f"TH1 {send_command('ArmFailSafe')} to the DUT with the ExpiryLengthSeconds field set to 900", None, verify_armfailsafe_response()), + TestStep( + 6, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster with the following fields: NOCValue and ICACValue", None, verify_noc_response("MissingCsr")), + TestStep( + 7, f"TH1 {send_command('CSRRequest')} with the IsForUpdateNOC field set to false", None, verify_csr_not_update()), + TestStep(8, "TH1 generates a new NOC chain with ICAC with the following properties"), + TestStep( + 9, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster", None, verify_constraint_error()), + TestStep( + 10, f"TH1 {send_command('CSRequest')} with the IsForUpdateNOC field set to true", None, verify_csr_not_update()), + TestStep( + 11, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster", None, verify_noc_response("InvalidPublicKey")), + TestStep(12, "TH1 generates a new Trusted Root Certificate and Private Key and saves as new_root_cert and new_root_key so that TH can generate an NOC for UpdateNOC that doesn’t chain to the original root"), + TestStep(13, "TH1 generates a new NOC and ICAC"), + TestStep( + 14, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster", None, verify_noc_response("InvalidNOC")), + TestStep(15, "TH1 generates a new NOC and ICAC"), + TestStep( + 16, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster", None, verify_noc_response("InvalidNOC")), + TestStep(17, "TH1 generates a new NOC and ICAC"), + TestStep( + 18, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster", None, verify_noc_response("InvalidNOC")), + TestStep( + 19, f"TH1 {send_command('AddTrustedRootCertificate')} to DUT again with the RootCACertificate field set to new_root_cert"), + TestStep( + 20, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster", None, verify_constraint_error()), + TestStep( + 21, f"TH1 {send_command('ArmFailSafe')} to the DUT with the ExpiryLengthSeconds field set to 0", None, verify_armfailsafe_response()), + TestStep(22, f"TH1 {send_command('OpenCommissioningWindow')} to the DUT"), + TestStep( + 23, f"TH1 connects to the DUT over PASE and {send_command('ArmFailSafe')} to the DUT with the ExpiryLengthSeconds field set to 900. Steps 24-26 are all performed over the PASE connection.", None, verify_armfailsafe_response()), + TestStep( + 24, f"TH1 {send_command('CSRequest')} over PASE with the IsForUpdateNOC field set to true", None, verify_csr_pase()), + TestStep(25, "TH1 generates a new NOC chain with ICAC with the following properties: new NOC and ICAC using icac_pase"), + TestStep(26, f"TH1 {send_command('UpdateNOC')} to the Node Operational Credentials cluster over PASE", None, verify_unsupported_access())] + + @async_test_body + async def test_TC_OPCREDS_3_4(self): + self.step(1) + opcreds = Clusters.OperationalCredentials + + self.step(2) + nocs = await self.read_single_attribute_check_success(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cluster=opcreds, attribute=opcreds.Attributes.NOCs, fabric_filtered=True) + if nocs[0].noc: + noc_original = nocs[0].noc + else: + asserts.assert_true(False, "Unexpected fail reading NOC Value on NOCs response") + + if nocs[0].icac: + icac_original = nocs[0].icac + else: + asserts.fail("Unexpected fail reading ICAC Value on NOCs response") + + self.step(3) + trusted_root_list_original = await self.read_single_attribute_check_success( + dev_ctrl=self.default_controller, + node_id=self.dut_node_id, cluster=opcreds, + attribute=opcreds.Attributes.TrustedRootCertificates) + asserts.assert_equal(len(trusted_root_list_original), 1, + "Unexpected number of entries in the TrustedRootCertificates table") + + self.step(4) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_original, ICACValue=icac_original) + try: + await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.fail("Unexpected error sending UpdateNOC command") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.FailsafeRequired, "Unexpected Failsafe status") + + self.step(5) + cmd = Clusters.GeneralCommissioning.Commands.ArmFailSafe(expiryLengthSeconds=900) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "Failure status returned from arm failsafe") + + self.step(6) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_original, ICACValue=icac_original) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.statusCode, opcreds.Enums.NodeOperationalCertStatusEnum.kMissingCsr, + "Failure status returned from UpdateNOC") + + self.step(7) + cmd = opcreds.Commands.CSRRequest(CSRNonce=random.randbytes(32), isForUpdateNOC=False) + csr_not_update = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + + self.step(8) + new_noc_chain = await self.default_controller.IssueNOCChain(csr_not_update, self.dut_node_id) + noc_not_for_update = new_noc_chain.nocBytes + icac_not_for_update = new_noc_chain.icacBytes + + self.step(9) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_not_for_update, ICACValue=icac_not_for_update) + try: + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.fail("Unexpected error sending UpdateNOC command") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.ConstraintError, "Failure status returned from UpdateNOC") + + cmd = Clusters.GeneralCommissioning.Commands.ArmFailSafe(0) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "Failure status returned from arm failsafe") + + cmd = Clusters.GeneralCommissioning.Commands.ArmFailSafe(900) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "Failure status returned from arm failsafe") + + self.step(10) + cmd = opcreds.Commands.CSRRequest(CSRNonce=random.randbytes(32), isForUpdateNOC=True) + csr_update = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + + self.step(11) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_original, ICACValue=icac_original) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.statusCode, opcreds.Enums.NodeOperationalCertStatusEnum.kInvalidPublicKey, + "Unexpected error code on AddNOC with mismatched CSR") + + self.step(12) + th1_ca_new = self.certificate_authority_manager.NewCertificateAuthority() + th1_fabric_admin_new = th1_ca_new.NewFabricAdmin(vendorId=0xFFF2, fabricId=self.matter_test_config.fabric_id) + th1_new = th1_fabric_admin_new.NewController(nodeId=self.default_controller.nodeId+1) + + self.step(13) + th1_certs_new = await th1_new.IssueNOCChain(csr_update, self.dut_node_id+1) + new_root_cert = th1_certs_new.rcacBytes + noc_update_new_root = th1_certs_new.nocBytes + icac_update_new_root = th1_certs_new.icacBytes + + self.step(14) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_update_new_root, ICACValue=icac_update_new_root) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.statusCode, opcreds.Enums.NodeOperationalCertStatusEnum.kInvalidNOC, + "NOCResponse with the StatusCode InvalidNOC") + + self.step(15) + # new NOC is generated from the NOCSR returned in csr_update with the matter-fabric-id set to a different + # value than noc_original. The NOC is signed by new ICA. Save as noc_update_bad_fabric_on_noc. + noc_update_bad_fabric_on_noc = th1_certs_new.nocBytes + # new ICAC is generated with the and matter-fabric-id omitted. ICAC is signed by the original key for + # trusted_root_original. Save as icac_update_bad_fabric_on_noc + icac_update_bad_fabric_on_noc = new_noc_chain.icacBytes + + self.step(16) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_update_bad_fabric_on_noc, ICACValue=icac_update_bad_fabric_on_noc) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.statusCode, opcreds.Enums.NodeOperationalCertStatusEnum.kInvalidNOC, + "NOCResponse with the StatusCode InvalidNOC") + + self.step(17) + noc_update_bad_fabric_on_icac = th1_certs_new.nocBytes + icac_update_bad_fabric_on_icac = new_noc_chain.icacBytes + + self.step(18) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_update_bad_fabric_on_icac, ICACValue=icac_update_bad_fabric_on_icac) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.statusCode, opcreds.Enums.NodeOperationalCertStatusEnum.kInvalidNOC, + "NOCResponse with the StatusCode InvalidNOC") + + self.step(19) + cmd = opcreds.Commands.AddTrustedRootCertificate(new_root_cert) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + + self.step(20) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_update_new_root, ICACValue=icac_update_new_root) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.statusCode, opcreds.Enums.NodeOperationalCertStatusEnum.kMissingCsr, + "Failure status returned from UpdateNOC") + + self.step(21) + cmd = Clusters.GeneralCommissioning.Commands.ArmFailSafe(0) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "Failure status returned from arm failsafe") + + self.step(22) + resp = await self.openCommissioningWindow(self.default_controller, self.dut_node_id) + + self.step(23) + await self.default_controller.FindOrEstablishPASESession(setupCode=resp.commissioningParameters.setupQRCode, nodeid=self.dut_node_id) + + cmd = Clusters.GeneralCommissioning.Commands.ArmFailSafe(900) + resp = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.assert_equal(resp.errorCode, Clusters.GeneralCommissioning.Enums.CommissioningErrorEnum.kOk, + "Error code status returned from arm failsafe") + + self.step(24) + cmd = opcreds.Commands.CSRRequest(CSRNonce=random.randbytes(32)) + csr_pase = await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + + self.step(25) + new_noc_chain = await self.default_controller.IssueNOCChain(csr_pase, self.dut_node_id) + noc_pase = csr_pase.NOCSRElements + icac_pase = new_noc_chain.icacBytes + + self.step(26) + cmd = opcreds.Commands.UpdateNOC(NOCValue=noc_pase, ICACValue=icac_pase) + try: + await self.send_single_cmd(dev_ctrl=self.default_controller, node_id=self.dut_node_id, cmd=cmd) + asserts.fail("Unexpected error sending UpdateNOC command") + except InteractionModelError as e: + asserts.assert_equal(e.status, Status.UnsupportedAccess, "Failure status returned from UpdateNOC") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/test_plan_support.py b/src/python_testing/test_plan_support.py index 3e332e1432..6abaf72a2d 100644 --- a/src/python_testing/test_plan_support.py +++ b/src/python_testing/test_plan_support.py @@ -25,6 +25,14 @@ def read_attribute(attribute: str, cluster: typing.Optional[str] = None): return attr +def send_command(command: str, cluster: typing.Optional[str] = None): + cmd = f"sends the {command} command" + if cluster: + return f'{cmd} from {cluster}' + else: + return cmd + + def save_as(val: str) -> str: return f' and saves the value as {val}' From 563ac33bf63c9d3506a003b6d25f0ef7ea2b0bf0 Mon Sep 17 00:00:00 2001 From: Jake Ororke Date: Mon, 25 Nov 2024 14:18:40 -0800 Subject: [PATCH 090/219] [Test] Creating TC_CADMIN_1_22 and TC_CADMIN_1_24 python test modules (#35632) * [Test] Creating TC_CADMIN_1_22 and TC_CADMIN_1_24: - Created CADMIN_1_22 python test module following steps in PR here: - Created CADMIN_1_24 python test module following steps in PR here: - Removed following yaml test modules: -- Test_TC_CADMIN_1_21.yaml, Test_TC_CADMIN_1_22.yaml, Test_TC_CADMIN_1_23.yaml, Test_TC_CADMIN_1_24.yaml * Restyled by autopep8 * Updating TC_CADMIN_1_22 and TC_CADMIN_1_24: - Resolved linting issues * Created TC_CADMIN_1_22_24 test module: - Merged TC_CADMIN_1_24 and TC_CADMIN_1_22 standalone test modules into a single test module - Found enum for window closed value and replaced it in the tests - Removed generate_unique_value and AttemptCommission functions - Updated CI arguments format to YAML'esque format * Restyled by autopep8 * Updated TC_CADMIN_1_22_24: - Renamed class to TC_CADMIN_1_22_24 * Updating TC_CADMIN_1_22_24: - Resolving lint errors * Update TC_CADMIN_1_22_24.py Updated to include dependency location change for matter_testing support module * Updated TC_CADMIN_1_22_24.py: - Resolved issues with CI args in TC_CADMIN_1_22_24 test module - Removed yaml calls for 1_21, 1_22, 1_23, and 1_24, also removed yaml call for 1_9 from manualTests.json * Updating TC_CADMIN_1_22_24 test module: - Resolving comments from tehampson as these were needed changes to be made -- Substituted to using cleaner code for assert.asserts_equal instead of just assert.failure -- Resolving copy paste error in TC_CADMIN_1_4 test -- Made comments cleaner by rewording to include what the error code was referring too * Update TC_CADMIN_1_22_24 test module: - Changing method for test step 3 on TC_CADMIN_1_24 test now using timeout for 30 seconds instead of revoke commissioning * Restyled by autopep8 * Update TC_CADMIN_1_22_24.py - Unnesting asserts from if statements * Update src/python_testing/TC_CADMIN_1_22_24.py - Adding this suggested change from Terrence into the code, as it does make the code much cleaner Co-authored-by: Terence Hampson * Update TC_CADMIN_1_22_24.py -Updating to changing static value to being stored in variable for easier readability as Terrence has suggested, making the code easier to read. * Restyled by autopep8 * Updated TC_CADMIN_1_22_24 test module: - Removed unneccessary await from asserts * Restyled by autopep8 --------- Co-authored-by: Restyled.io Co-authored-by: Terence Hampson --- .../certification/Test_TC_CADMIN_1_21.yaml | 123 ----------- .../certification/Test_TC_CADMIN_1_22.yaml | 199 ------------------ .../certification/Test_TC_CADMIN_1_23.yaml | 124 ----------- .../certification/Test_TC_CADMIN_1_24.yaml | 199 ------------------ src/app/tests/suites/manualTests.json | 5 - src/python_testing/TC_CADMIN_1_22_24.py | 179 ++++++++++++++++ 6 files changed, 179 insertions(+), 650 deletions(-) delete mode 100644 src/app/tests/suites/certification/Test_TC_CADMIN_1_21.yaml delete mode 100644 src/app/tests/suites/certification/Test_TC_CADMIN_1_22.yaml delete mode 100644 src/app/tests/suites/certification/Test_TC_CADMIN_1_23.yaml delete mode 100644 src/app/tests/suites/certification/Test_TC_CADMIN_1_24.yaml create mode 100644 src/python_testing/TC_CADMIN_1_22_24.py diff --git a/src/app/tests/suites/certification/Test_TC_CADMIN_1_21.yaml b/src/app/tests/suites/certification/Test_TC_CADMIN_1_21.yaml deleted file mode 100644 index f6e7332a9d..0000000000 --- a/src/app/tests/suites/certification/Test_TC_CADMIN_1_21.yaml +++ /dev/null @@ -1,123 +0,0 @@ -# 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. - -name: - 30.1.21. [TC-CADMIN-1.21] Open commissioning window - durations max and - max+1 [BCM] [DUT - Commissionee] - -PICS: - - CADMIN.S - - CADMIN.S.F00 - -config: - nodeId: 0x12344321 - timeout: 950 - endpoint: 0 - payload: - type: char_string - defaultValue: "MT:-24J0AFN00KA0648G00" - -tests: - - label: "Precondition: Reset Devices to factory defaults" - PICS: PICS_SDK_CI_ONLY - cluster: "SystemCommands" - command: "FactoryReset" - - - label: "Precondition: Reset Devices to factory defaults" - verification: | - Reset Devices to factory defaults - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Factory Reset the DUT and enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: "Step 1: TH_CR1 starts a commissioning process with DUT_CE" - cluster: "CommissionerCommands" - command: "PairWithCode" - PICS: CADMIN.S - arguments: - values: - - name: "nodeId" - value: nodeId - - name: "payload" - value: payload - - - label: "Step 1: TH_CR1 commissioned with DUT_CE" - cluster: "DelayCommands" - command: "WaitForCommissionee" - PICS: CADMIN.S - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: - "Step 2: TH_CR1 opens a commissioning window on DUT_CE using BCM with - a value of 900 seconds" - cluster: "Administrator Commissioning" - command: "OpenBasicCommissioningWindow" - timedInteractionTimeoutMs: 10000 - PICS: CADMIN.S.C01.Rsp - arguments: - values: - - name: "CommissioningTimeout" - value: 900 - - - label: "Step 3: Wait 901 seconds for commissioning Window to be closed" - PICS: CADMIN.S.C01.Rsp - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: 901000 - - - label: - "Step 4: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 - - - label: - "Step 5: TH_CR1 opens a commissioning window on DUT_CE using BCM with - a value of 901 seconds" - cluster: "Administrator Commissioning" - command: "OpenBasicCommissioningWindow" - PICS: CADMIN.S.C01.Rsp - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 901 - response: - error: INVALID_COMMAND - - - label: - "Step 6: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 diff --git a/src/app/tests/suites/certification/Test_TC_CADMIN_1_22.yaml b/src/app/tests/suites/certification/Test_TC_CADMIN_1_22.yaml deleted file mode 100644 index 4b94b6518a..0000000000 --- a/src/app/tests/suites/certification/Test_TC_CADMIN_1_22.yaml +++ /dev/null @@ -1,199 +0,0 @@ -# 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. - -name: - 30.1.22. [TC-CADMIN-1.22] Open commissioning window - durations max and - max+1 [ECM] [DUT - Commissionee] - -PICS: - - CADMIN.S - -config: - nodeId: 0x12344321 - timeout: 950 - endpoint: 0 - payload: - type: char_string - defaultValue: "MT:-24J0AFN00KA0648G00" - discriminator: - type: int16u - defaultValue: 3840 - PakeVerifier: - type: octet_string - defaultValue: "hex:b96170aae803346884724fe9a3b287c30330c2a660375d17bb205a8cf1aecb350457f8ab79ee253ab6a8e46bb09e543ae422736de501e3db37d441fe344920d09548e4c18240630c4ff4913c53513839b7c07fcc0627a1b8573a149fcd1fa466cf" - -tests: - - label: "Precondition: Reset Devices to factory defaults" - cluster: "SystemCommands" - PICS: PICS_SDK_CI_ONLY - command: "FactoryReset" - - - label: "Precondition: Reset Devices to factory defaults" - verification: | - Reset Devices to factory defaults - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Factory Reset the DUT and enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: "Step 1: TH_CR1 starts a commissioning process with DUT_CE" - cluster: "CommissionerCommands" - command: "PairWithCode" - PICS: CADMIN.S - arguments: - values: - - name: "nodeId" - value: nodeId - - name: "payload" - value: payload - - - label: "Step 1: TH_CR1 commissioned with DUT_CE" - cluster: "DelayCommands" - command: "WaitForCommissionee" - PICS: CADMIN.S.C00.Rsp - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: - "Step 2: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 900 seconds" - verification: | - On TH_CR1 - (chip tool), open commissioning window - - ./chip-tool pairing open-commissioning-window 1 1 900 1000 3840 - - Verify Manual pairing code on TH_CR1(chip-tool) Log - - [1635925713.966786][9695:9700] CHIP:SC: Success status report received. Session was established - [1635925713.966839][9695:9700] CHIP:IN: New secure session created for device 0x0000000000000001, key 33!! - [1635925713.966938][9695:9700] CHIP:CTL: OpenCommissioningWindow for device ID 1 - [1635925713.972601][9695:9700] CHIP:DMG: ICR moving to [AddingComm] - [1635925713.972705][9695:9700] CHIP:DMG: ICR moving to [AddedComma] - [1635925713.972815][9695:9700] CHIP:IN: Prepared encrypted message 0xaaaad9b57d10 to 0x0000000000000001 of type 0x8 and protocolId (0, 1) on exchange 31056i with MessageCounter:0. - [1635925713.972876][9695:9700] CHIP:IN: Sending encrypted msg 0xaaaad9b57d10 with MessageCounter:0 to 0x0000000000000001 at monotonic time: 13449459 msec - [1635925713.973006][9695:9700] CHIP:DMG: ICR moving to [CommandSen] - [1635925713.973061][9695:9700] CHIP:CTL: Manual pairing code: [35484132896] - [1635925713.973120][9695:9700] CHIP:CTL: SetupQRCode: [MT:00000CQM00A7F87ZT10] - [1635925713.973178][9695:9700] CHIP:EM: Sending Standalone Ack for MessageCounter:1964916542 on exchange 31055i - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && CADMIN.S.C00.Rsp - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: - "Step 2a: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 900 seconds" - cluster: "Administrator Commissioning" - command: "OpenCommissioningWindow" - PICS: CADMIN.S.C00.Rsp && PICS_SDK_CI_ONLY - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 900 - - name: "PAKEPasscodeVerifier" - value: PakeVerifier - - name: "Discriminator" - value: discriminator - - name: "Iterations" - value: 1000 - - name: "Salt" - value: "SPAKE2P Key Salt" - - - label: "Step 3: Wait for commissioning Window to 901 seconds" - PICS: CADMIN.S.C00.Rsp - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: 901000 - - - label: - "Step 4: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 - - - label: - "Step 5: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 901 seconds" - verification: | - On TH_CR1 (chip tool), open commissioning window - - ./chip-tool pairing open-commissioning-window 1 1 901 2000 3841 - - Verify DUT_CE responds General error 0x85 on TH_CR1 (chip-tool) log - - CHIP:DMG: Received Command Response Status for Endpoint=0 Cluster=0x0000_003C Command=0x0000_0001 Status=0x85 - [1652860801.225084][9512:9517] CHIP:TOO: Error: IM Error 0x00000585: General error: 0x85 (INVALID_COMMAND) - [1652860801.225173][9512:9517] CHIP:DMG: ICR moving to [AwaitingDe] - [1652860801.225294][9512:9517] CHIP:EM: Sending Standalone Ack for MessageCounter:4191961 on exchange 37827i - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && CADMIN.S.C00.Rsp - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: - "Step 5a: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 901 seconds" - cluster: "Administrator Commissioning" - command: "OpenCommissioningWindow" - PICS: CADMIN.S.C00.Rsp && PICS_SDK_CI_ONLY - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 901 - - name: "PAKEPasscodeVerifier" - value: PakeVerifier - - name: "Discriminator" - value: discriminator - - name: "Iterations" - value: 1000 - - name: "Salt" - value: "SPAKE2P Key Salt" - response: - error: INVALID_COMMAND - - - label: - "Step 6: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 diff --git a/src/app/tests/suites/certification/Test_TC_CADMIN_1_23.yaml b/src/app/tests/suites/certification/Test_TC_CADMIN_1_23.yaml deleted file mode 100644 index 9aab51aa38..0000000000 --- a/src/app/tests/suites/certification/Test_TC_CADMIN_1_23.yaml +++ /dev/null @@ -1,124 +0,0 @@ -# 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. - -name: - 24.1.23. [TC-CADMIN-1.23] Open commissioning window - durations max and - max+1 [BCM] [DUT - Commissionee] - -PICS: - - CADMIN.S - - CADMIN.S.F00 - -config: - nodeId: 0x12344321 - timeout: 200 - endpoint: 0 - payload: - type: char_string - defaultValue: "MT:-24J0AFN00KA0648G00" - -tests: - - label: "Precondition: Reset Devices to factory defaults" - PICS: PICS_SDK_CI_ONLY - cluster: "SystemCommands" - command: "FactoryReset" - - - label: "Precondition: Reset Devices to factory defaults" - verification: | - Reset Devices to factory defaults - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Factory Reset the DUT and enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: "Step 1: TH_CR1 starts a commissioning process with DUT_CE" - cluster: "CommissionerCommands" - command: "PairWithCode" - PICS: CADMIN.S - arguments: - values: - - name: "nodeId" - value: nodeId - - name: "payload" - value: payload - - - label: "Step 1: TH_CR1 commissioned with DUT_CE" - cluster: "DelayCommands" - command: "WaitForCommissionee" - PICS: CADMIN.S.C01.Rsp - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: - "Step 2: TH_CR1 opens a commissioning window on DUT_CE using BCM with - a value of 180 seconds" - cluster: "Administrator Commissioning" - command: "OpenBasicCommissioningWindow" - PICS: CADMIN.S.C01.Rsp - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 180 - - - label: - "Step 3: Wait for 181 seconds for commissioning Window to be closed" - PICS: CADMIN.S.C01.Rsp - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: 181000 - - - label: - "Step 4: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 - - - label: - "Step 5: TH_CR1 opens a commissioning window on DUT_CE using BCM with - a value of 179 seconds" - cluster: "Administrator Commissioning" - command: "OpenBasicCommissioningWindow" - PICS: CADMIN.S.C01.Rsp - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 179 - response: - error: INVALID_COMMAND - - - label: - "Step 6: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 diff --git a/src/app/tests/suites/certification/Test_TC_CADMIN_1_24.yaml b/src/app/tests/suites/certification/Test_TC_CADMIN_1_24.yaml deleted file mode 100644 index 8e201988cc..0000000000 --- a/src/app/tests/suites/certification/Test_TC_CADMIN_1_24.yaml +++ /dev/null @@ -1,199 +0,0 @@ -# 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. - -name: - 24.1.24. [TC-CADMIN-1.24] Open commissioning window - durations max and - max+1 [ECM] [DUT - Commissionee] - -PICS: - - CADMIN.S - -config: - nodeId: 0x12344321 - timeout: 200 - endpoint: 0 - payload: - type: char_string - defaultValue: "MT:-24J0AFN00KA0648G00" - discriminator: - type: int16u - defaultValue: 3840 - PakeVerifier: - type: octet_string - defaultValue: "hex:b96170aae803346884724fe9a3b287c30330c2a660375d17bb205a8cf1aecb350457f8ab79ee253ab6a8e46bb09e543ae422736de501e3db37d441fe344920d09548e4c18240630c4ff4913c53513839b7c07fcc0627a1b8573a149fcd1fa466cf" - -tests: - - label: "Precondition: Reset Devices to factory defaults" - cluster: "SystemCommands" - PICS: PICS_SDK_CI_ONLY - command: "FactoryReset" - - - label: "Precondition: Reset Devices to factory defaults" - verification: | - Reset Devices to factory defaults - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP - arguments: - values: - - name: "message" - value: "Factory Reset the DUT and enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: "Step 1: TH_CR1 starts a commissioning process with DUT_CE" - cluster: "CommissionerCommands" - command: "PairWithCode" - PICS: CADMIN.S - arguments: - values: - - name: "nodeId" - value: nodeId - - name: "payload" - value: payload - - - label: "Step 1: TH_CR1 commissioned with DUT_CE" - cluster: "DelayCommands" - command: "WaitForCommissionee" - PICS: CADMIN.S.C00.Rsp - arguments: - values: - - name: "nodeId" - value: nodeId - - - label: - "Step 2: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 180 seconds" - verification: | - On TH_CR1 ( chip tool), open commissioning window - - ./chip-tool pairing open-commissioning-window 1 1 180 1000 3840 - - Verify Manual pairing code on TH_CR1(chip-tool) Log - - [1635925713.966786][9695:9700] CHIP:SC: Success status report received. Session was established - [1635925713.966839][9695:9700] CHIP:IN: New secure session created for device 0x0000000000000001, key 33!! - [1635925713.966938][9695:9700] CHIP:CTL: OpenCommissioningWindow for device ID 1 - [1635925713.972601][9695:9700] CHIP:DMG: ICR moving to [AddingComm] - [1635925713.972705][9695:9700] CHIP:DMG: ICR moving to [AddedComma] - [1635925713.972815][9695:9700] CHIP:IN: Prepared encrypted message 0xaaaad9b57d10 to 0x0000000000000001 of type 0x8 and protocolId (0, 1) on exchange 31056i with MessageCounter:0. - [1635925713.972876][9695:9700] CHIP:IN: Sending encrypted msg 0xaaaad9b57d10 with MessageCounter:0 to 0x0000000000000001 at monotonic time: 13449459 msec - [1635925713.973006][9695:9700] CHIP:DMG: ICR moving to [CommandSen] - [1635925713.973061][9695:9700] CHIP:CTL: Manual pairing code: [35484132896] - [1635925713.973120][9695:9700] CHIP:CTL: SetupQRCode: [MT:00000CQM00A7F87ZT10] - [1635925713.973178][9695:9700] CHIP:EM: Sending Standalone Ack for MessageCounter:1964916542 on exchange 31055i - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && CADMIN.S.C00.Rsp - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: - "Step 2a: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 180 seconds" - cluster: "Administrator Commissioning" - command: "OpenCommissioningWindow" - PICS: CADMIN.S.C00.Rsp && PICS_SDK_CI_ONLY - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 180 - - name: "PAKEPasscodeVerifier" - value: PakeVerifier - - name: "Discriminator" - value: discriminator - - name: "Iterations" - value: 1000 - - name: "Salt" - value: "SPAKE2P Key Salt" - - - label: "Step 3: Wait for commissioning Window to 181 seconds" - PICS: CADMIN.S.C00.Rsp - cluster: "DelayCommands" - command: "WaitForMs" - arguments: - values: - - name: "ms" - value: 181000 - - - label: - "Step 4: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 - - - label: - "Step 5: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 179 seconds" - verification: | - On TH_CR1 ( chip tool), open commissioning window - - ./chip-tool pairing open-commissioning-window 1 1 179 2000 3841 - - Verify DUT_CE responds General error 0x85 on TH_CR1 (chip-tool) log - - CHIP:DMG: Received Command Response Status for Endpoint=0 Cluster=0x0000_003C Command=0x0000_0001 Status=0x85 - [1652860801.225084][9512:9517] CHIP:TOO: Error: IM Error 0x00000585: General error: 0x85 (INVALID_COMMAND) - [1652860801.225173][9512:9517] CHIP:DMG: ICR moving to [AwaitingDe] - [1652860801.225294][9512:9517] CHIP:EM: Sending Standalone Ack for MessageCounter:4191961 on exchange 37827i - cluster: "LogCommands" - command: "UserPrompt" - PICS: PICS_SKIP_SAMPLE_APP && CADMIN.S.C00.Rsp - arguments: - values: - - name: "message" - value: "Enter 'y' after success" - - name: "expectedValue" - value: "y" - - - label: - "Step 5a: TH_CR1 opens a commissioning window on DUT_CE using ECM with - a value of 179 seconds" - cluster: "Administrator Commissioning" - command: "OpenCommissioningWindow" - PICS: CADMIN.S.C00.Rsp && PICS_SDK_CI_ONLY - timedInteractionTimeoutMs: 10000 - arguments: - values: - - name: "CommissioningTimeout" - value: 179 - - name: "PAKEPasscodeVerifier" - value: PakeVerifier - - name: "Discriminator" - value: discriminator - - name: "Iterations" - value: 1000 - - name: "Salt" - value: "SPAKE2P Key Salt" - response: - error: INVALID_COMMAND - - - label: - "Step 6: TH_CR1 reads the window status to verify the DUT_CE window is - closed" - cluster: "Administrator Commissioning" - command: "readAttribute" - attribute: "WindowStatus" - PICS: CADMIN.S.A0000 - response: - value: 0 diff --git a/src/app/tests/suites/manualTests.json b/src/app/tests/suites/manualTests.json index 0e6e045b8e..4b7961b29d 100644 --- a/src/app/tests/suites/manualTests.json +++ b/src/app/tests/suites/manualTests.json @@ -176,17 +176,12 @@ "Test_TC_CADMIN_1_18", "Test_TC_CADMIN_1_19", "Test_TC_CADMIN_1_20", - "Test_TC_CADMIN_1_21", - "Test_TC_CADMIN_1_22", "Test_TC_CADMIN_1_3", "Test_TC_CADMIN_1_4", "Test_TC_CADMIN_1_5", "Test_TC_CADMIN_1_6", - "Test_TC_CADMIN_1_9", "Test_TC_CADMIN_1_10", "Test_TC_CADMIN_1_13", - "Test_TC_CADMIN_1_23", - "Test_TC_CADMIN_1_24", "Test_TC_CADMIN_1_25", "Test_TC_CADMIN_1_26" ], diff --git a/src/python_testing/TC_CADMIN_1_22_24.py b/src/python_testing/TC_CADMIN_1_22_24.py new file mode 100644 index 0000000000..464ed6df8e --- /dev/null +++ b/src/python_testing/TC_CADMIN_1_22_24.py @@ -0,0 +1,179 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --PICS src/app/tests/suites/certification/ci-pics-values +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import asyncio +import logging +import random +from time import sleep + +import chip.clusters as Clusters +from chip.ChipDeviceCtrl import CommissioningParameters +from chip.exceptions import ChipStackError +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CADMIN_1_22_24(MatterBaseTest): + async def OpenCommissioningWindow(self) -> CommissioningParameters: + try: + params = await self.th1.OpenCommissioningWindow( + nodeid=self.dut_node_id, timeout=self.max_window_duration, iteration=10000, discriminator=self.discriminator, option=1) + return params + + except Exception as e: + logging.exception('Error running OpenCommissioningWindow %s', e) + asserts.fail('Failed to open commissioning window') + + async def get_window_status(self) -> int: + AC_cluster = Clusters.AdministratorCommissioning + window_status = await self.read_single_attribute_check_success(dev_ctrl=self.th1, fabric_filtered=False, endpoint=0, cluster=AC_cluster, attribute=AC_cluster.Attributes.WindowStatus) + return window_status + + def pics_TC_CADMIN_1_22(self) -> list[str]: + return ["CADMIN.S"] + + def steps_TC_CADMIN_1_22(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "TH_CR1 opens a commissioning window on DUT_CE using ECM with a value of 900 seconds", + "DUT_CE opens its Commissioning window to allow a second commissioning"), + TestStep(3, "TH_CR1 sends an RevokeCommissioning command to the DUT"), + TestStep(4, "TH_CR1 reads the window status to verify the DUT_CE window is closed", + "DUT_CE windows status shows the window is closed"), + TestStep(5, "TH_CR1 opens a commissioning window on DUT_CE using ECM with a value of 901 seconds", + "DUT_CE does not open its Commissioning window to allow a second commissioning. DUT_CE shows 'Failed to open commissioning window. Global status 0x85'"), + TestStep(6, "TH_CR1 reads the window status to verify the DUT_CE window is closed", + "DUT_CE windows status shows the window is closed"), + ] + + @async_test_body + async def test_TC_CADMIN_1_22(self): + self.step(1) + self.th1 = self.default_controller + self.discriminator = random.randint(0, 4095) + + self.step(2) + await self.th1.OpenCommissioningWindow( + nodeid=self.dut_node_id, timeout=900, iteration=10000, discriminator=self.discriminator, option=1) + + self.step(3) + revokeCmd = Clusters.AdministratorCommissioning.Commands.RevokeCommissioning() + await self.th1.SendCommand(nodeid=self.dut_node_id, endpoint=0, payload=revokeCmd, timedRequestTimeoutMs=6000) + # The failsafe cleanup is scheduled after the command completes, so give it a bit of time to do that + sleep(1) + + self.step(4) + window_status = await self.get_window_status() + asserts.assert_equal(window_status, Clusters.AdministratorCommissioning.Enums.CommissioningWindowStatusEnum.kWindowNotOpen, + "Commissioning window is expected to be closed, but was found to be open") + + self.step(5) + try: + await self.th1.OpenCommissioningWindow( + nodeid=self.dut_node_id, timeout=901, iteration=10000, discriminator=self.discriminator, option=1) + + except ChipStackError as e: + # Since we provided 901 seconds as the timeout duration, + # we should not be able to open comm window as duration is too long. + # we are expected receive Failed to open commissioning window: IM Error 0x00000585: General error: 0x85 (INVALID_COMMAND) + _INVALID_COMMAND = 0x00000585 + asserts.assert_equal(e.err, _INVALID_COMMAND, + "Expected to error as we provided failure value for opening commissioning window") + + self.step(6) + window_status2 = await self.get_window_status() + asserts.assert_equal(window_status2, Clusters.AdministratorCommissioning.Enums.CommissioningWindowStatusEnum.kWindowNotOpen, + "Commissioning window is expected to be closed, but was found to be open") + + def pics_TC_CADMIN_1_24(self) -> list[str]: + return ["CADMIN.S"] + + def steps_TC_CADMIN_1_24(self) -> list[TestStep]: + return [ + TestStep(1, "Commissioning, already done", is_commissioning=True), + TestStep(2, "TH_CR1 opens a commissioning window on DUT_CE using ECM with a value of 180 seconds", + "DUT_CE opens its Commissioning window to allow a second commissioning"), + TestStep(3, "Wait for the commissioning window in step 2 to timeout"), + TestStep(4, "TH_CR1 reads the window status to verify the DUT_CE window is closed", + "DUT_CE windows status shows the window is closed"), + TestStep(5, "TH_CR1 opens a commissioning window on DUT_CE using ECM with a value of 179 seconds", + "DUT_CE does not open its Commissioning window to allow a second commissioning. DUT_CE shows 'Failed to open commissioning window. Global status 0x85'"), + TestStep(6, "TH_CR1 reads the window status to verify the DUT_CE window is closed", + "DUT_CE windows status shows the window is closed"), + ] + + @async_test_body + async def test_TC_CADMIN_1_24(self): + self.step(1) + self.th1 = self.default_controller + self.discriminator = random.randint(0, 4095) + + self.step(2) + await self.th1.OpenCommissioningWindow( + nodeid=self.dut_node_id, timeout=180, iteration=10000, discriminator=self.discriminator, option=1) + + self.step(3) + sleep(180) + + self.step(4) + # TODO: Issue noticed when initially attempting to check window status after waiting for timeout to occur, issue is detailed here: https://github.com/project-chip/connectedhomeip/issues/35983 + # Workaround in place below until above issue resolved + try: + window_status = await self.get_window_status() + except asyncio.CancelledError: + window_status = await self.get_window_status() + + asserts.assert_equal(window_status, Clusters.AdministratorCommissioning.Enums.CommissioningWindowStatusEnum.kWindowNotOpen, + "Commissioning window is expected to be closed, but was found to be open") + + self.step(5) + try: + await self.th1.OpenCommissioningWindow( + nodeid=self.dut_node_id, timeout=179, iteration=10000, discriminator=self.discriminator, option=1) + + except ChipStackError as e: + # Since we provided 179 seconds as the timeout duration, + # we should not be able to open comm window as duration is too long. + # we are expected receive Failed to open commissioning window: IM Error 0x00000585: General error: 0x85 (INVALID_COMMAND) + _INVALID_COMMAND = 0x00000585 + asserts.assert_equal(e.err, _INVALID_COMMAND, + "Expected to error as we provided failure value for opening commissioning window") + + self.step(6) + window_status2 = await self.get_window_status() + asserts.assert_equal(window_status2, Clusters.AdministratorCommissioning.Enums.CommissioningWindowStatusEnum.kWindowNotOpen, + "Commissioning window is expected to be closed, but was found to be open") + + +if __name__ == "__main__": + default_matter_test_main() From d6a1870d6fb00a007852bc9a5a8d935c0743a2dc Mon Sep 17 00:00:00 2001 From: Jake Ororke Date: Mon, 25 Nov 2024 14:18:44 -0800 Subject: [PATCH 091/219] [Test] Creating CADMIN 1.19 python3 test module (#35611) * [Test] Creating CADMIN 1.19 test module: - Test module created following steps in PR: https://github.com/CHIP-Specifications/chip-test-plans/pull/4669 * Restyled by autopep8 * Update TC_CADMIN_1_19 test module: - Resolving linting issues * Removing yaml test module for TC_CADMIN_1_19: - Removed yaml test as we have created python test module in its place * Update TC_CADMIN_1_19.py - Removed debugging print statements as no longer needed in test code * Update src/python_testing/TC_CADMIN_1_19.py Co-authored-by: C Freeman * Update src/python_testing/TC_CADMIN_1_19.py Co-authored-by: C Freeman * Updating TC_CADMIN_1_19 and matter_testing scripts: - Updated CI Arguments - Updated dependency location for matter_testing_support - Removed local OpenCommissioningWindow function, updated to using MatterBaseTest version - Removed local CommissioningAttempt function, moved to using function call directly in test - Removed initialization of TH2 controller as not needed - Removed additional dictionary names and delimited it down to just using numbers instead. - Updated matter_testing support script to include setting timeout value dynamically in openCommissioningWindow function * Restyled by autopep8 * Update TC_CADMIN_1_19.py Resolving Linting errors * Update TC_CADMIN_1_19.py - Moved location of print_step to top of for range for creating virtual fragments - Removed unnecessary print_step for catching error * Updated TC_CADMIN_1_19 test module: - Created new variable for current_fabric + 1 - Replaced if statements with asserts.assert_equal() - Changed start of range from 1 to 0 - Changed test steps to match test plan better, removed test step 1 * Restyled by autopep8 * Updated TC_CADMIN_1_19 test module: - Added new criteria to test step 3 where max_fabrics is checked to make sure it is greater than initial_fabrics count * Updated TC_CADMIN_1_19 test module: - Removed print statement from debugging session * Restyled by autopep8 --------- Co-authored-by: Restyled.io Co-authored-by: C Freeman --- .../certification/Test_TC_CADMIN_1_19.yaml | 127 ------------- src/python_testing/TC_CADMIN_1_19.py | 172 ++++++++++++++++++ .../chip/testing/matter_testing.py | 4 +- 3 files changed, 174 insertions(+), 129 deletions(-) delete mode 100644 src/app/tests/suites/certification/Test_TC_CADMIN_1_19.yaml create mode 100644 src/python_testing/TC_CADMIN_1_19.py diff --git a/src/app/tests/suites/certification/Test_TC_CADMIN_1_19.yaml b/src/app/tests/suites/certification/Test_TC_CADMIN_1_19.yaml deleted file mode 100644 index 892ae3c627..0000000000 --- a/src/app/tests/suites/certification/Test_TC_CADMIN_1_19.yaml +++ /dev/null @@ -1,127 +0,0 @@ -# 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. -# Auto-generated scripts for harness use only, please review before automation. The endpoints and cluster names are currently set to default - -name: - 4.1.19. [TC-CADMIN-1.19] max number of Commissioned Fabrics and - SupportedFabrics rollover using ECM [DUT - Commissionee] -PICS: - - CADMIN.S - -config: - nodeId: 0x12344321 - cluster: "Basic Information" - endpoint: 0 - -tests: - - label: "Precondition" - verification: | - Reset Devices to factory defaults - disabled: true - - - label: "Step 1: TH_CR1 starts a commissioning process with DUT_CE" - PICS: CADMIN.S - verification: | - "1. Provision the device using TH_CR1 -chip tool(use above instructions) , - " - disabled: true - - - label: - "Step 2: TH_CR1 opens a commissioning window on DUT_CE using a - commissioning timeout of PIXIT.CADMIN.CwDuration seconds using ECM" - PICS: CADMIN.S.C00.Rsp - verification: | - On TH_CR1 (chip tool), open commissioning window using ECM - - ./chip-tool pairing open-commissioning-window 1 1 300 1000 3840 - - Verify Manual pairing code on TH_CR1 (chip-tool) Log - - [1635925713.966786][9695:9700] CHIP:SC: Success status report received. Session was established - [1635925713.966839][9695:9700] CHIP:IN: New secure session created for device 0x0000000000000001, key 33!! - [1635925713.966938][9695:9700] CHIP:CTL: OpenCommissioningWindow for device ID 1 - [1635925713.972601][9695:9700] CHIP:DMG: ICR moving to [AddingComm] - [1635925713.972705][9695:9700] CHIP:DMG: ICR moving to [AddedComma] - [1635925713.972815][9695:9700] CHIP:IN: Prepared encrypted message 0xaaaad9b57d10 to 0x0000000000000001 of type 0x8 and protocolId (0, 1) on exchange 31056i with MessageCounter:0. - [1635925713.972876][9695:9700] CHIP:IN: Sending encrypted msg 0xaaaad9b57d10 with MessageCounter:0 to 0x0000000000000001 at monotonic time: 13449459 msec - [1635925713.973006][9695:9700] CHIP:DMG: ICR moving to [CommandSen] - [1635925713.973061][9695:9700] CHIP:CTL: Manual pairing code: [36217551633] - [1635925713.973120][9695:9700] CHIP:CTL: SetupQRCode: [MT:00000CQM00A7F87ZT10] - [1635925713.973178][9695:9700] CHIP:EM: Sending Standalone Ack for MessageCounter:1964916542 on exchange 31055i - disabled: true - - - label: "Step 3: THn starts a commissioning process with DUT_CE" - PICS: CADMIN.S - verification: | - On TH_CR1+1 controller using chip tool connect to the accessory - - - ./chip-tool pairing code 2 36217551633 --commissioner-name beta - - Verify you got below message on TH_CR1+1(chip-tool) log - Device commissioning completed with success - disabled: true - - - label: - "Step 4: Repeat Step 3 and Step 4 an additional (SupportedFabrics - 2) - times to reach an index value of SupportedFabrics on DUT_CE" - PICS: CADMIN.S.C00.Rsp - verification: | - Repeat step 3 until CommissionedFabrics=SupportedFabrics (Supported fabrics value obtained in the precondition) - - Use the following command to verify the currentcommissioned fabric (Output number may vary depends on the number successful commissioning ) - - ./chip-tool operationalcredentials read commissioned-fabrics 1 0 - - [1660907933.677983][33780:33785] CHIP:TOO: CommissionedFabrics: 16 - disabled: true - - - label: - "Step 5: THn_1 starts a commissioning process and opens a - commissioning window with DUT_CE" - PICS: CADMIN.S - verification: | - On THnth controller using chip tool connect to the accessory - - ./chip-tool pairing code 6 36217551633 --commissioner-name 4 - - Verify DUT_CE responds with NOCResponse with a StatusCode of 0x05 on THn (chip-tool) log - - CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_003E Command=0x0000_0008 - [1649756670.402192][10794:10799] CHIP:CTL: Device returned status 5 on receiving the NOC - [1649756670.402221][10794:10799] CHIP:CTL: Add NOC failed with error ../../third_party/connectedhomeip/src/controller/CHIPDeviceController.cpp:1110: CHIP Error 0x0000000B: No memory - [1649756670.402241][10794:10799] CHIP:CTL: Failed to perform commissioning step 13 - disabled: true - - - label: "Step 6: TH_CR1 removes FabricIndex1" - PICS: OPCREDS.S.C0a.Rsp - verification: | - on TH_CR1 using chip tool, remove fabric with FabricIndex=1 - - ./chip-tool operationalcredentials remove-fabric 1 1 0 - - CHIP:DMG: Received Command Response Data, Endpoint=0 Cluster=0x0000_003E Command=0x0000_0008 - CHIP:TOO: Endpoint: 0 Cluster: 0x0000_003E Command 0x0000_0008 - CHIP:TOO: NOCResponse: { - CHIP:TOO: statusCode: 0 - CHIP:TOO: fabricIndex: 1 - CHIP:TOO: } - CHIP:DMG: ICR moving to [AwaitingDe] - - Verify CommissionedFabrics=SupportedFabrics-1 on TH_CR1(chip-tool) log - - ./chip-tool operationalcredentials read commissioned-fabrics 2 0 --commissioner-name beta - - [1660907933.677983][33780:33785] CHIP:TOO: CommissionedFabrics: 15 - disabled: true diff --git a/src/python_testing/TC_CADMIN_1_19.py b/src/python_testing/TC_CADMIN_1_19.py new file mode 100644 index 0000000000..5ec3da867d --- /dev/null +++ b/src/python_testing/TC_CADMIN_1_19.py @@ -0,0 +1,172 @@ +# +# Copyright (c) 2024 Project CHIP Authors +# All rights reserved. +# +# 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. +# +# === BEGIN CI TEST ARGUMENTS === +# test-runner-runs: +# run1: +# app: ${ALL_CLUSTERS_APP} +# app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json +# script-args: > +# --storage-path admin_storage.json +# --commissioning-method on-network +# --discriminator 1234 +# --passcode 20202021 +# --trace-to json:${TRACE_TEST_JSON}.json +# --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto +# --PICS src/app/tests/suites/certification/ci-pics-values +# factory-reset: true +# quiet: true +# === END CI TEST ARGUMENTS === + +import random + +import chip.clusters as Clusters +from chip import ChipDeviceCtrl +from chip.exceptions import ChipStackError +from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main +from mobly import asserts + + +class TC_CADMIN_1_19(MatterBaseTest): + def generate_unique_random_value(self, value): + while True: + random_value = random.randint(10000000, 99999999) + asserts.assert_equal(random_value, value) + return random_value + + async def get_fabrics(self, th: ChipDeviceCtrl) -> int: + OC_cluster = Clusters.OperationalCredentials + fabrics = await self.read_single_attribute_check_success(dev_ctrl=th, fabric_filtered=False, endpoint=0, cluster=OC_cluster, attribute=OC_cluster.Attributes.Fabrics) + return fabrics + + def steps_TC_CADMIN_1_19(self) -> list[TestStep]: + return [ + TestStep( + 1, "TH_CR1 reads the BasicCommissioningInfo attribute from the General Commissioning cluster and saves the MaxCumulativeFailsafeSeconds field as max_window_duration."), + TestStep(2, "TH_CR1 reads the Fabrics attribute from the Node Operational Credentials cluster using a non-fabric-filtered read. Save the number of fabrics in the list as initial_number_of_fabrics"), + TestStep(3, "TH_CR1 reads the SupportedFabrics attribute from the Node Operational Credentials cluster. Save max_fabrics", + "Verify that max_fabrics is larger than initial_number_of_fabrics. If not, instruct the tester to remove one non-test-harness fabric and re-start the test."), + TestStep(4, "Repeat the following steps (5a and 5b) max_fabrics - initial_number_of_fabrics times"), + TestStep( + "4a", "TH_CR1 send an OpenCommissioningWindow command to DUT_CE using a commissioning timeout of max_window_duration", "{resDutSuccess}"), + TestStep("4b", "TH creates a controller on a new fabric and commissions DUT_CE using that controller", + "Commissioning is successful"), + TestStep(5, "TH reads the CommissionedFabrics attributes from the Node Operational Credentials cluster.", + "Verify this is equal to max_fabrics"), + TestStep( + 6, "TH_CR1 send an OpenCommissioningWindow command to DUT_CE using a commissioning timeout of max_window_duration", "{resDutSuccess}"), + TestStep(7, "TH creates a controller on a new fabric and commissions DUT_CE using that controller", + "Verify DUT_CE responds with NOCResponse with a StatusCode field value of TableFull(5)"), + TestStep(8, "Repeat the following steps (9a and 9b) for each controller (TH_CRn) created by this test"), + TestStep("8a", "The controller reads the CurrentFabricIndex from the Node Operational Credentials cluster. Save as fabric_index."), + TestStep("8b", "TH_CR1 sends the RemoveFabric command to DUT_CE", "{resDutSuccess}"), + TestStep(9, "TH reads the CommissionedFabrics attributes from the Node Operational Credentials cluster.", + "Verify this is equal to initial_number_of_fabrics."), + ] + + def pics_TC_CADMIN_1_19(self) -> list[str]: + return ["CADMIN.S"] + + @async_test_body + async def test_TC_CADMIN_1_19(self): + self.step(1) + # Establishing TH1 + self.th1 = self.default_controller + + GC_cluster = Clusters.GeneralCommissioning + attribute = GC_cluster.Attributes.BasicCommissioningInfo + duration = await self.read_single_attribute_check_success(endpoint=0, cluster=GC_cluster, attribute=attribute) + self.max_window_duration = duration.maxCumulativeFailsafeSeconds + + self.step(2) + fabrics = await self.get_fabrics(th=self.th1) + initial_number_of_fabrics = len(fabrics) + + self.step(3) + OC_cluster = Clusters.OperationalCredentials + max_fabrics = await self.read_single_attribute_check_success(dev_ctrl=self.th1, fabric_filtered=False, endpoint=0, cluster=OC_cluster, attribute=OC_cluster.Attributes.SupportedFabrics) + asserts.assert_greater(max_fabrics, initial_number_of_fabrics, + "max fabrics must be greater than initial fabrics, please remove one non-test-harness fabric and try test again") + + self.step(4) + fids_ca_dir = {} + fids_fa_dir = {} + fids = {} + for fid in range(0, max_fabrics - initial_number_of_fabrics): + self.print_step("commissioning iteration", fid + 1) + # Make sure that current test step is 5, resets here after each loop + self.current_step_index = 4 + + self.step("4a") + params = await self.openCommissioningWindow(dev_ctrl=self.th1, timeout=self.max_window_duration, node_id=self.dut_node_id) + + self.step("4b") + fids_ca_dir[fid] = self.certificate_authority_manager.NewCertificateAuthority() + fids_fa_dir[fid] = fids_ca_dir[fid].NewFabricAdmin(vendorId=0xFFF1, fabricId=fid + 1) + fids[fid] = fids_fa_dir[fid].NewController(nodeId=fid + 1) + + await fids[fid].CommissionOnNetwork( + nodeId=self.dut_node_id, setupPinCode=params.commissioningParameters.setupPinCode, + filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=params.randomDiscriminator) + + self.step(5) + # TH reads the CommissionedFabrics attributes from the Node Operational Credentials cluster + current_fabrics = await self.read_single_attribute_check_success(dev_ctrl=self.th1, fabric_filtered=False, endpoint=0, cluster=OC_cluster, attribute=OC_cluster.Attributes.SupportedFabrics) + asserts.assert_equal(current_fabrics, max_fabrics, "Expected number of fabrics not correct") + + self.step(6) + params = await self.openCommissioningWindow(dev_ctrl=self.th1, node_id=self.dut_node_id) + + self.step(7) + # TH creates a controller on a new fabric and attempts to commission DUT_CE using that controller + next_fabric = current_fabrics + 1 + fids_ca_dir[next_fabric] = self.certificate_authority_manager.NewCertificateAuthority() + fids_fa_dir[next_fabric] = fids_ca_dir[current_fabrics + + 1].NewFabricAdmin(vendorId=0xFFF1, fabricId=next_fabric) + try: + fids[next_fabric] = fids_fa_dir[next_fabric].NewController(nodeId=next_fabric) + await fids[next_fabric].CommissionOnNetwork( + nodeId=self.dut_node_id, setupPinCode=params.commissioningParameters.setupPinCode, + filterType=ChipDeviceCtrl.DiscoveryFilterType.LONG_DISCRIMINATOR, filter=params.randomDiscriminator) + + except ChipStackError as e: + # When attempting to create a new controller we are expected to get the following response: + # src/credentials/FabricTable.cpp:833: CHIP Error 0x0000000B: No memory + # Since the FabricTable is full and unable to create any new fabrics + self.print_step("Max number of fabrics", "reached") + asserts.assert_equal(e.err, 0x0000000B, + "Expected to return table is full since max number of fabrics has been created already") + + self.step(8) + for thc in fids.keys(): + # Make sure that current test step is 11 (9 + 2 since 5a and 5b test steps included in count), resets here after each loop + self.current_step_index = 10 + + self.step("8a") + fabric_index = await self.read_single_attribute_check_success(dev_ctrl=fids[thc], endpoint=0, cluster=OC_cluster, attribute=OC_cluster.Attributes.CurrentFabricIndex) + + self.step("8b") + removeFabricCmd = Clusters.OperationalCredentials.Commands.RemoveFabric(fabric_index) + await self.th1.SendCommand(nodeid=self.dut_node_id, endpoint=0, payload=removeFabricCmd) + + self.step(9) + # TH reads the CommissionedFabrics attributes from the Node Operational Credentials cluster. + current_fabrics = await self.read_single_attribute_check_success(dev_ctrl=self.th1, fabric_filtered=False, endpoint=0, cluster=OC_cluster, attribute=OC_cluster.Attributes.CommissionedFabrics) + asserts.assert_equal(current_fabrics, initial_number_of_fabrics, "Expected number of fabrics not correct") + + +if __name__ == "__main__": + default_matter_test_main() diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index bb3666f551..a88b57e602 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -1141,10 +1141,10 @@ def check_pics(self, pics_key: str) -> bool: def is_pics_sdk_ci_only(self) -> bool: return self.check_pics('PICS_SDK_CI_ONLY') - async def openCommissioningWindow(self, dev_ctrl: ChipDeviceCtrl, node_id: int) -> CustomCommissioningParameters: + async def openCommissioningWindow(self, dev_ctrl: ChipDeviceCtrl, node_id: int, timeout: int = 900) -> CustomCommissioningParameters: rnd_discriminator = random.randint(0, 4095) try: - commissioning_params = await dev_ctrl.OpenCommissioningWindow(nodeid=node_id, timeout=900, iteration=1000, + commissioning_params = await dev_ctrl.OpenCommissioningWindow(nodeid=node_id, timeout=timeout, iteration=1000, discriminator=rnd_discriminator, option=1) params = CustomCommissioningParameters(commissioning_params, rnd_discriminator) return params From 0ac52eb9471401ebe69654a64b9c010e6fe390a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Tue, 26 Nov 2024 00:02:25 +0100 Subject: [PATCH 092/219] [Silabs] Add Trigger events from Matter CLI to README (#36570) * Add refrigeratoralarm event to README.md Add refrigeratoralarm event * Update README.md * Update README.md Trigger events from Matter CLI * restyled * Update .wordlist.txt to add refrigeratoralarm * Update Refrigerator README.md --- .github/.wordlist.txt | 1 + examples/refrigerator-app/silabs/README.md | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt index c43d780c0f..9d916059a9 100644 --- a/.github/.wordlist.txt +++ b/.github/.wordlist.txt @@ -1195,6 +1195,7 @@ rebase recommand recommanded recurse +refrigeratoralarm regen registerAttributeAccessOverride RegisterCommandHandler diff --git a/examples/refrigerator-app/silabs/README.md b/examples/refrigerator-app/silabs/README.md index d063937a6d..7d6a426af1 100644 --- a/examples/refrigerator-app/silabs/README.md +++ b/examples/refrigerator-app/silabs/README.md @@ -314,8 +314,24 @@ combination with JLinkRTTClient as follows: ``` chip-tool refrigeratorandtemperaturecontrolledcabinetmode chip-tool temperaturecontrol - chip-tool refrigeratoralarm + ``` + + Subscribe refrigeratoralarm events + + ``` + chip-tool interactive start + refrigeratoralarm subscribe-event notify 1 10 1 1 + ``` +## Trigger events from Matter CLI + +**door-state-change** + +- Trigger refrigeratoralarm door-state-change event: + + ``` + -> matterCli> refrigeratoralarm event door-state-change open + -> Done ``` ### Notes From e782f539cb74348977036d8a20e03b5d6c52d4a6 Mon Sep 17 00:00:00 2001 From: Martin Girardot <165289184+Martin-NXP@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:51:13 +0100 Subject: [PATCH 093/219] [NXP] Add EL2GO factory data impl, change default rw61x factory data impl (#36615) * [NXP][platform] Add EL2GO factory data implementation, update default factory data implmentation to use secure element Signed-off-by: Martin Girardot * [NXP][exmples] Add EL2GO factory data implementation, update default factory data implmentation to use secure element Signed-off-by: Martin Girardot * [NXP][script] Add EL2GO factory data implementation Signed-off-by: Martin Girardot * [NXP][doc] Add EL2GO factory data implementation, update default factory data implmentation to use secure element Signed-off-by: Martin Girardot * Restyled by whitespace * Restyled by clang-format * Restyled by gn * Restyled by prettier-markdown * Restyled by autopep8 * Restyled by isort * [NXP] fix spelling Signed-off-by: Martin Girardot * [NXP][submodule] Update NXP matter support submodule Signed-off-by: Martin Girardot * [NXP] Add factory data secure key storage compatiblity with actual factory data Signed-off-by: Martin Girardot --------- Signed-off-by: Martin Girardot Co-authored-by: Restyled.io --- docs/platforms/nxp/nxp_manufacturing_flow.md | 115 +++---- .../all-clusters-app/nxp/rt/rw61x/BUILD.gn | 15 +- .../laundry-washer-app/nxp/rt/rw61x/BUILD.gn | 13 +- examples/thermostat/nxp/rt/rw61x/BUILD.gn | 15 +- .../nxp/factory_data_generator/custom.py | 27 ++ .../nxp/factory_data_generator/generate.py | 37 ++- .../common/factory_data/FactoryDataProvider.h | 21 +- src/platform/nxp/rt/rw61x/BUILD.gn | 34 +-- .../rt/rw61x/FactoryDataProviderEl2GoImpl.cpp | 283 ++++++++++++++++++ .../rt/rw61x/FactoryDataProviderEl2GoImpl.h | 77 +++++ .../nxp/rt/rw61x/FactoryDataProviderImpl.cpp | 119 +++++++- .../nxp/rt/rw61x/FactoryDataProviderImpl.h | 9 +- third_party/nxp/nxp_matter_support | 2 +- 13 files changed, 621 insertions(+), 146 deletions(-) create mode 100644 src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.cpp create mode 100644 src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.h diff --git a/docs/platforms/nxp/nxp_manufacturing_flow.md b/docs/platforms/nxp/nxp_manufacturing_flow.md index 28618b276a..0f30d0612b 100644 --- a/docs/platforms/nxp/nxp_manufacturing_flow.md +++ b/docs/platforms/nxp/nxp_manufacturing_flow.md @@ -103,8 +103,6 @@ Here is the interpretation of the **required** parameters: --hw_version -> Hardware Version as number --hw_version_str -> Hardware Version as string --cert_declaration -> path to the Certification Declaration (der format) location ---dac_cert -> path to the DAC (der format) location ---dac_key -> path to the DAC key (der format) location --pai_cert -> path to the PAI (der format) location --spake2p_path -> path to the spake2p tool --out -> name of the binary that will be used for storing all the generated data @@ -113,6 +111,11 @@ Here is the interpretation of the **required** parameters: Here is the interpretation of the **optional** parameters: ```shell +--dac_cert -> path to the DAC certificate (der format) location +--dac_key -> path to the DAC key (der format) location +--EL2GO_bin -> path to the EdgeLock 2Go binary (bin format) location +--EL2GO_DAC_KEY_ID -> DAC key ID configured into EdgeLock 2Go as hex value +--EL2GO_DAC_CERT_ID -> DAC certificate ID configured into EdgeLock 2Go as hex value --dac_key_password -> Password to decode DAC key --dac_key_use_sss_blob -> Used when --dac_key contains a path to an encrypted blob, instead of the actual DAC private key. The blob metadata size is 24, so the total length @@ -182,17 +185,56 @@ Also, demo **DAC**, **PAI** and **PAA** certificates needed in case ## 6. Increased security for DAC private key -### 6.1 SSS-based platforms +### 6.1 SSS-based with EdgeLock2go support + +EdgeLock2go services could be used to securely provisioned DAC key/cert during +manufacturing. + +Prior to the generation of the factory data binary. `EL2GO` data needs to be +generated following `EL2GO` process. + +For the factory data generation following option need to be added: + +`--EL2GO_bin ~/secure_objects.bin` containing `EL2GO` information including +encrypted DAC private key and certificate. `--EL2GO_DAC_KEY_ID 1234` containing +corresponding to the ID of the DAC key chosen during `EL2GO` key generation. +`--EL2GO_DAC_CERT_ID 4321` containing corresponding to the ID of the DAC +certification chosen during `EL2GO` key generation. + +Reference factory data generation command: + +```shell +python3 ./scripts/tools/nxp/factory_data_generator/generate.py -i 10000 -s UXKLzwHdN3DZZLBaL2iVGhQi/OoQwIwJRQV4rpEalbA= -p ${passcode} -d ${discriminator} --vid "0x$VID" --pid "0x$PID" --vendor_name "NXP Semiconductors" --product_name "Thermostat" --serial_num "12345678" --date "$DATE" --hw_version 1 --hw_version_str "1.0" --cert_declaration $FACTORY_DATA_DEST/Chip-Test-CD-$VID-$PID.der --EL2GO_bin ~/secure_objects.bin --EL2GO_DAC_KEY_ID 1234 --EL2GO_DAC_CERT_ID 4321 --pai_cert $FACTORY_DATA_DEST/Chip-PAI-NXP-$VID-$PID-Cert.der --spake2p_path ./out/spake2p --unique_id "00112233445566778899aabbccddeeff" --out $FACTORY_DATA_DEST/factory_data.bin +``` + +Supported platforms: + +- `rw61x` + +In addition to the GN flag `nxp_use_factory_data=true`, a Matter application +needs to be built with `nxp_enable_secure_EL2GO_factory_data=true` to allow +loading of EdgeLock2go data to the secure element. + +In this mode EdgeLock2go keys will always remain encrypted and only usable by +the `SSS`. In this case, all operations that requires DAC private access will be +transferred to the `SSS`. + +### 6.2 SSS-based without EdgeLock2go support for DAC private key secure storage Supported platforms: - `k32w1` - `mcxw71` +- `rw61x` For platforms that have a secure subsystem (`SSS`), the DAC private key can be converted to an encrypted blob. This blob will overwrite the DAC private key in -factory data and will be imported in the `SSS` at initialization, by the factory -data provider instance. +factory data and will be imported in the `SSS` by the factory data provider +instance. + +In this architecture, outside of the manufacturing flow, the DAC private will +always remain usable only by the `SSS`. In this case, all operations that +requires DAC private access will be transferred to the `SSS`. The application will check at initialization whether the DAC private key has been converted or not and convert it if needed. However, the conversion process @@ -226,64 +268,5 @@ Please note that `--dac_key` now points to a binary file that contains the encrypted blob. The user can use the DAC private in plain text instead of using the `SSS` by -adding the following gn argument `chip_use_plain_dac_key=true`. - -### 6.2 RW61X - -Supported platforms: - -- RW61X - -there are three implementations for factory data protection - -- whole factory data protection with AES encryption ( - nxp_use_factory_data=true nxp_enable_secure_whole_factory_data=true ) - `examples/platform/nxp/rt/rw61x/factory_data/source/AppFactoryDataExample.cpp`\ - `src/platform/nxp/rt/rw61x/FactoryDataProviderEncImpl.cpp` - -- only dac private key protection ( nxp_use_factory_data=true - nxp_enable_secure_dac_private_key_storage=true ) - `examples/platform/nxp/rt/rw61x/factory_data/source/AppFactoryDataExample.cpp` - \ - `src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.cpp` - -- whole factory data protection with hard-coded AES key ( - nxp_use_factory_data=true ) - `examples/platform/nxp/common/factory_data/source/AppFactoryDataDefaultImpl.cpp` - \ - `src/platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.cpp` - -for the first one, the whole factory data is encrypted by an AES-256 key, the -AES key can be passed through serial link when in factory production mode, and -will be provisioned into Edge Lock, and the returned AES Key blob (wrapped key) -can be stored in the end of factory data region in TLV format. for the -decryption process, the blob is retrieved and provisioned into Edge Lock and the -whole factory data can be decrypted using the returned key index in Edge Lock. -Compared with only dac private key protection solution, this solution can avoid -tampering with the original factory data. - -the factory data should be encrypted by an AES-256 key using "--aes256_key" -option in "generate.py" script file. - -it will check whether there is AES key blob in factory data region when in each -initialization, if not, the default AES key is converted and the result is -stored into flash, it run only once. - -for the second one, it only protect the dac private key inside the factory data, -the dac private key is retrieved and provisioned into Edge Lock, the returned -key blob replace the previous dac private key, and also update the overall size -and hash, and re-write the factory data. when device is doing matter -commissioning, the blob is retrieved and provisioned into Edge Lock and the -signing can be done using the returned key index in Edge Lock. - -the factory data should be plain text for the first programming. it will check -whether there is dac private key blob (base on the size of blob, should be 48) -in factory data when in each initialization, if not, the dac private key is -converted and the result is stored into flash, it run only once. - -for the third one, it is a little similar to the first one, the whole factory -data is encrypted by an AES key, but there are two differences: - -- the AES key is hard-coded and not provisioned into Edge Lock -- the factory data should be encrypted by AES-128 key using "--aes128_key" - option in "generate.py" script file. +adding the following gn argument `chip_use_plain_dac_key=true` (not supported on +rw61x). diff --git a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn index 73f2153838..5b73da4bc9 100644 --- a/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/all-clusters-app/nxp/rt/rw61x/BUILD.gn @@ -1,5 +1,5 @@ # Copyright (c) 2021 Project CHIP Authors -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -55,15 +55,6 @@ app_common_folder = "all-clusters-app/all-clusters-common" rt_sdk("sdk") { defines = [] - # To be moved, temporary mbedtls config fix to build app with factory data - if (nxp_enable_secure_dac_private_key_storage || - nxp_enable_secure_whole_factory_data) { - defines += [ - "MBEDTLS_NIST_KW_C", - "MBEDTLS_PSA_CRYPTO_CLIENT", - ] - } - cflags = [] public_deps = [] public_configs = [] @@ -141,8 +132,8 @@ rt_executable("all_cluster_app") { "../../common/main/main.cpp", ] - if (nxp_enable_secure_dac_private_key_storage || - nxp_enable_secure_whole_factory_data) { + if (nxp_enable_secure_whole_factory_data || + nxp_enable_secure_EL2GO_factory_data) { sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] if (nxp_enable_secure_whole_factory_data) { defines += [ "ENABLE_SECURE_WHOLE_FACTORY_DATA" ] diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn index 936f1de4a7..063cf49b81 100644 --- a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn @@ -56,15 +56,6 @@ app_common_folder = "laundry-washer-app/nxp/zap" rt_sdk("sdk") { defines = [] - # To be moved, temporary mbedtls config fix to build app with factory data - if (nxp_enable_secure_dac_private_key_storage || - nxp_enable_secure_whole_factory_data) { - defines += [ - "MBEDTLS_NIST_KW_C", - "MBEDTLS_PSA_CRYPTO_CLIENT", - ] - } - cflags = [] public_deps = [] public_configs = [] @@ -142,8 +133,8 @@ rt_executable("laundry-washer") { "../../common/main/main.cpp", ] - if (nxp_enable_secure_dac_private_key_storage || - nxp_enable_secure_whole_factory_data) { + if (nxp_enable_secure_whole_factory_data || + nxp_enable_secure_EL2GO_factory_data) { sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] if (nxp_enable_secure_whole_factory_data) { defines += [ "ENABLE_SECURE_WHOLE_FACTORY_DATA" ] diff --git a/examples/thermostat/nxp/rt/rw61x/BUILD.gn b/examples/thermostat/nxp/rt/rw61x/BUILD.gn index ec0a6d4f0e..07a58e9477 100644 --- a/examples/thermostat/nxp/rt/rw61x/BUILD.gn +++ b/examples/thermostat/nxp/rt/rw61x/BUILD.gn @@ -1,5 +1,5 @@ # Copyright (c) 2021 Project CHIP Authors -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -58,15 +58,6 @@ app_common_folder = "thermostat/nxp/zap" rt_sdk("sdk") { defines = [] - # To be moved, temporary mbedtls config fix to build app with factory data - if (nxp_enable_secure_dac_private_key_storage || - nxp_enable_secure_whole_factory_data) { - defines += [ - "MBEDTLS_NIST_KW_C", - "MBEDTLS_PSA_CRYPTO_CLIENT", - ] - } - cflags = [] public_deps = [] public_configs = [] @@ -165,8 +156,8 @@ rt_executable("thermostat") { ] } - if (nxp_enable_secure_dac_private_key_storage || - nxp_enable_secure_whole_factory_data) { + if (nxp_enable_secure_whole_factory_data || + nxp_enable_secure_EL2GO_factory_data) { sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] if (nxp_enable_secure_whole_factory_data) { defines += [ "ENABLE_SECURE_WHOLE_FACTORY_DATA" ] diff --git a/scripts/tools/nxp/factory_data_generator/custom.py b/scripts/tools/nxp/factory_data_generator/custom.py index 179f990c30..87d3b7dca3 100644 --- a/scripts/tools/nxp/factory_data_generator/custom.py +++ b/scripts/tools/nxp/factory_data_generator/custom.py @@ -337,3 +337,30 @@ def encode(self): def max_length(self): return 64 + + +class El2GoObject(FileArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 24 + + +class El2GoDacKeyID(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 25 + + +class El2GoDacCertID(IntArgument): + + def __init__(self, arg): + super().__init__(arg) + + def key(self): + return 26 diff --git a/scripts/tools/nxp/factory_data_generator/generate.py b/scripts/tools/nxp/factory_data_generator/generate.py index 945f8bde64..a36f0153fb 100755 --- a/scripts/tools/nxp/factory_data_generator/generate.py +++ b/scripts/tools/nxp/factory_data_generator/generate.py @@ -23,10 +23,10 @@ import sys from crc import Calculator, Crc16 -from custom import (CertDeclaration, DacCert, DacPKey, Discriminator, HardwareVersion, HardwareVersionStr, IterationCount, - ManufacturingDate, PaiCert, PartNumber, ProductFinish, ProductId, ProductLabel, ProductName, - ProductPrimaryColor, ProductURL, Salt, SerialNum, SetupPasscode, StrArgument, UniqueId, VendorId, VendorName, - Verifier) +from custom import (CertDeclaration, DacCert, DacPKey, Discriminator, El2GoDacCertID, El2GoDacKeyID, El2GoObject, HardwareVersion, + HardwareVersionStr, IterationCount, ManufacturingDate, PaiCert, PartNumber, ProductFinish, ProductId, + ProductLabel, ProductName, ProductPrimaryColor, ProductURL, Salt, SerialNum, SetupPasscode, StrArgument, + UniqueId, VendorId, VendorName, Verifier) from default import InputArgument # Global variable for hash ID @@ -75,13 +75,24 @@ def __init__(self, args): self.spake2p = Spake2p() if self.args.spake2p_verifier is None: self.spake2p.generate(self.args) - self.args.dac_key.generate_private_key(self.args.dac_key_password, self.args.dac_key_use_sss_blob) + if self.args.dac_key: + self.args.dac_key.generate_private_key(self.args.dac_key_password, self.args.dac_key_use_sss_blob) def _validate_args(self): - if self.args.dac_key_password is None: + if self.args.dac_key_password is None and self.args.EL2GO_bin is None: logging.warning( "DAC Key password not provided. It means DAC Key is not protected." ) + if self.args.dac_key and self.args.EL2GO_bin: + logging.error("Could not provide two DAC Key provisionning method at the same time") + + if (not self.args.dac_key or not self.args.dac_cert) and not self.args.EL2GO_bin: + logging.error("Need to provide a DAC provisionner") + raise Exception("Could not generate factory data") + + if self.args.EL2GO_bin and (not self.args.EL2GO_DAC_CERT_ID or not self.args.EL2GO_DAC_KEY_ID): + logging.error("Need to provide EdgeLock 2Go DAC IDs") + raise Exception("Could not generate factory data") str_args = [obj for key, obj in vars(self.args).items() if isinstance(obj, StrArgument)] for str_arg in str_args: @@ -210,10 +221,6 @@ def main(): help="[str] Hardware version as string") required.add_argument("--cert_declaration", required=True, type=CertDeclaration, help="[path] Path to Certification Declaration in DER format") - required.add_argument("--dac_cert", required=True, type=DacCert, - help="[path] Path to DAC certificate in DER format") - required.add_argument("--dac_key", required=True, type=DacPKey, - help="[path] Path to DAC key in DER format") required.add_argument("--pai_cert", required=True, type=PaiCert, help="[path] Path to PAI certificate in DER format") required.add_argument("--spake2p_path", required=True, type=str, @@ -221,6 +228,16 @@ def main(): required.add_argument("--out", required=True, type=str, help="[path] Path to output binary") + optional.add_argument("--dac_cert", type=DacCert, + help="[path] Path to DAC certificate in DER format") + optional.add_argument("--dac_key", type=DacPKey, + help="[path] Path to DAC key in DER format") + optional.add_argument("--EL2GO_bin", type=El2GoObject, + help="[path] Path to EL2GO secure objects binary") + optional.add_argument("--EL2GO_DAC_KEY_ID", type=El2GoDacKeyID, + help="[hex] EL2GO DAC key ID") + optional.add_argument("--EL2GO_DAC_CERT_ID", type=El2GoDacCertID, + help="[hex] EL2GO DAC certificate ID") optional.add_argument("--dac_key_password", type=str, help="[path] Password to decode DAC Key if available") optional.add_argument("--dac_key_use_sss_blob", action='store_true', diff --git a/src/platform/nxp/common/factory_data/FactoryDataProvider.h b/src/platform/nxp/common/factory_data/FactoryDataProvider.h index b06089270a..58ad20d7b9 100644 --- a/src/platform/nxp/common/factory_data/FactoryDataProvider.h +++ b/src/platform/nxp/common/factory_data/FactoryDataProvider.h @@ -1,7 +1,7 @@ /* * * Copyright (c) 2023 Project CHIP Authors - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,21 @@ namespace chip { namespace DeviceLayer { +#define CHIP_FACTORY_DATA_ERROR(e) \ + ChipError(ChipError::Range::kLastRange, ((uint8_t) ChipError::Range::kLastRange << 2) | e, __FILE__, __LINE__) + +#define CHIP_FACTORY_DATA_SHA_CHECK CHIP_FACTORY_DATA_ERROR(0x01) +#define CHIP_FACTORY_DATA_HEADER_READ CHIP_FACTORY_DATA_ERROR(0x02) +#define CHIP_FACTORY_DATA_HASH_ID CHIP_FACTORY_DATA_ERROR(0x03) +#define CHIP_FACTORY_DATA_PDM_RESTORE CHIP_FACTORY_DATA_ERROR(0x04) +#define CHIP_FACTORY_DATA_NULL CHIP_FACTORY_DATA_ERROR(0x05) +#define CHIP_FACTORY_DATA_FLASH_ERASE CHIP_FACTORY_DATA_ERROR(0x06) +#define CHIP_FACTORY_DATA_FLASH_PROGRAM CHIP_FACTORY_DATA_ERROR(0x07) +#define CHIP_FACTORY_DATA_INTERNAL_FLASH_READ CHIP_FACTORY_DATA_ERROR(0x08) +#define CHIP_FACTORY_DATA_PDM_SAVE_RECORD CHIP_FACTORY_DATA_ERROR(0x09) +#define CHIP_FACTORY_DATA_PDM_READ_RECORD CHIP_FACTORY_DATA_ERROR(0x0A) +#define CHIP_FACTORY_DATA_RESTORE_MECHANISM CHIP_FACTORY_DATA_ERROR(0x0B) + class FactoryDataProviderImpl; /** @@ -72,6 +87,10 @@ class FactoryDataProvider : public chip::Credentials::DeviceAttestationCredentia kProductLabel, kProductFinish, kProductPrimaryColor, + kEl2GoBlob, + kEl2GoDacKeyId, + kEl2GoDacCertId, + kMaxId }; diff --git a/src/platform/nxp/rt/rw61x/BUILD.gn b/src/platform/nxp/rt/rw61x/BUILD.gn index 13c2b3c2ff..684faf3a7f 100644 --- a/src/platform/nxp/rt/rw61x/BUILD.gn +++ b/src/platform/nxp/rt/rw61x/BUILD.gn @@ -1,5 +1,5 @@ # Copyright (c) 2021 Project CHIP Authors -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -52,18 +52,18 @@ config("nxp_platform_config") { "CONFIG_CHIP_ENCRYPTED_FACTORY_DATA=1", ] - if (nxp_enable_secure_dac_private_key_storage) { - assert(nxp_enable_secure_dac_private_key_storage && - !nxp_enable_secure_whole_factory_data, - "please select only one protection solution") - defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/rt/rw61x/FactoryDataProviderImpl.h\"" ] - } else if (nxp_enable_secure_whole_factory_data) { + if (nxp_enable_secure_whole_factory_data) { assert(nxp_enable_secure_whole_factory_data && - !nxp_enable_secure_dac_private_key_storage, + !nxp_enable_secure_EL2GO_factory_data, "please select only one protection solution") defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/rt/rw61x/FactoryDataProviderEncImpl.h\"" ] + } else if (nxp_enable_secure_EL2GO_factory_data) { + assert(!nxp_enable_secure_whole_factory_data && + nxp_enable_secure_EL2GO_factory_data, + "please select only one protection solution") + defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.h\"" ] } else { - defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/common/factory_data/FactoryDataProviderFwkImpl.h\"" ] + defines += [ "EXTERNAL_FACTORY_DATA_PROVIDER_IMPL_HEADER=\"platform/nxp/rt/rw61x/FactoryDataProviderImpl.h\"" ] } } @@ -201,20 +201,20 @@ static_library("nxp_platform") { "../../common/factory_data/FactoryDataProvider.cpp", "../../common/factory_data/FactoryDataProvider.h", ] - if (nxp_enable_secure_dac_private_key_storage) { - sources += [ - "FactoryDataProviderImpl.cpp", - "FactoryDataProviderImpl.h", - ] - } else if (nxp_enable_secure_whole_factory_data) { + if (nxp_enable_secure_whole_factory_data) { sources += [ "FactoryDataProviderEncImpl.cpp", "FactoryDataProviderEncImpl.h", ] + } else if (nxp_enable_secure_EL2GO_factory_data) { + sources += [ + "FactoryDataProviderEl2GoImpl.cpp", + "FactoryDataProviderEl2GoImpl.h", + ] } else { sources += [ - "../../common/factory_data/FactoryDataProviderFwkImpl.cpp", - "../../common/factory_data/FactoryDataProviderFwkImpl.h", + "FactoryDataProviderImpl.cpp", + "FactoryDataProviderImpl.h", ] } diff --git a/src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.cpp b/src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.cpp new file mode 100644 index 0000000000..d7919201af --- /dev/null +++ b/src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.cpp @@ -0,0 +1,283 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright 2024 NXP + * + * 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. + */ + +#include "FactoryDataProviderEl2GoImpl.h" + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +#include "ELSFactoryData.h" +#include "mflash_drv.h" + +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) +#include "els_pkc_mbedtls.h" +#endif /* defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) */ + +#include "fsl_adapter_flash.h" + +/* mbedtls */ +#include "mbedtls/aes.h" +#include "mbedtls/sha256.h" + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +#ifndef FACTORY_DATA_PROVIDER_LOG +#define FACTORY_DATA_PROVIDER_LOG 0 +#endif + +#if FACTORY_DATA_PROVIDER_LOG +#include "fsl_debug_console.h" +#define FACTORY_DATA_PROVIDER_PRINTF(...) \ + PRINTF("[%s] ", __FUNCTION__); \ + PRINTF(__VA_ARGS__); \ + PRINTF("\n\r"); +#else +#define FACTORY_DATA_PROVIDER_PRINTF(...) +#endif + +/* Grab symbol for the base address from the linker file. */ +extern uint32_t __FACTORY_DATA_START_OFFSET[]; +extern uint32_t __FACTORY_DATA_SIZE[]; + +using namespace ::chip::Credentials; +using namespace ::chip::Crypto; + +namespace chip { +namespace DeviceLayer { + +FactoryDataProviderImpl FactoryDataProviderImpl::sInstance; + +CHIP_ERROR FactoryDataProviderImpl::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, + uint32_t * contentAddr) +{ + CHIP_ERROR err = CHIP_ERROR_NOT_FOUND; + uint8_t type = 0; + uint32_t index = 0; + uint8_t * addrContent = NULL; + uint8_t * factoryDataAddress = &factoryDataRamBuffer[0]; + uint32_t factoryDataSize = sizeof(factoryDataRamBuffer); + uint16_t currentLen = 0; + + while (index < factoryDataSize) + { + /* Read the type */ + memcpy((uint8_t *) &type, factoryDataAddress + index, sizeof(type)); + index += sizeof(type); + + /* Read the len */ + memcpy((uint8_t *) ¤tLen, factoryDataAddress + index, sizeof(currentLen)); + index += sizeof(currentLen); + + /* Check if the type gotten is the expected one */ + if (searchedType == type) + { + FACTORY_DATA_PROVIDER_PRINTF("type = %d, currentLen = %d, bufLength =%d", type, currentLen, bufLength); + /* If pBuf is null it means that we only want to know if the Type has been found */ + if (pBuf != NULL) + { + /* If the buffer given is too small, fill only the available space */ + if (bufLength < currentLen) + { + currentLen = bufLength; + } + memcpy((uint8_t *) pBuf, factoryDataAddress + index, currentLen); + } + length = currentLen; + if (contentAddr != NULL) + { + *contentAddr = (uint32_t) factoryDataAddress + index; + } + err = CHIP_NO_ERROR; + break; + } + else if (type == 0) + { + /* No more type available , break the loop */ + break; + } + else + { + /* Jump to next data */ + index += currentLen; + } + } + + return err; +} + +CHIP_ERROR FactoryDataProviderImpl::GetDeviceAttestationCert(MutableByteSpan & outBuffer) +{ + status_t status = STATUS_SUCCESS; + uint8_t el2go_blob[EL2GO_MAX_BLOB_SIZE] = { 0U }; + size_t el2go_blob_size = 0U; + size_t outBufferSize = 0U; + uint16_t CertificateIdSize = 0; + uint16_t BlobSize = 0; + uint32_t Addr; + uint32_t el2go_dac_cert_id = 0; + + /* Search key ID FactoryDataId::kEl2GoBlob address */ + ReturnErrorOnFailure(SearchForId(FactoryDataId::kEl2GoBlob, NULL, 0, BlobSize, &Addr)); + ReturnErrorOnFailure( + SearchForId(FactoryDataId::kEl2GoDacCertId, (uint8_t *) &el2go_dac_cert_id, sizeof(el2go_dac_cert_id), CertificateIdSize)); + + /* Read DAC certificate from EL2GO data */ + status = + read_el2go_blob((uint8_t *) Addr, (size_t) BlobSize, el2go_dac_cert_id, el2go_blob, EL2GO_MAX_BLOB_SIZE, &el2go_blob_size); + + STATUS_SUCCESS_OR_EXIT_MSG("DAC Private key not found: 0x%08x", status); + + // Import EL2GO blobs in ELS + status = decrypt_el2go_cert_blob(el2go_blob, el2go_blob_size, outBuffer.data(), outBuffer.size(), &outBufferSize); + outBuffer.reduce_size(outBufferSize); + STATUS_SUCCESS_OR_EXIT_MSG("decrypt_el2go_cert_blob failed: 0x%08x", status); + + return CHIP_NO_ERROR; + +exit: + return CHIP_ERROR_INTERNAL; +} + +CHIP_ERROR FactoryDataProviderImpl::ReadAndCheckFactoryDataInFlash(void) +{ + status_t status; + uint32_t factoryDataAddress = (uint32_t) __FACTORY_DATA_START_OFFSET; + uint32_t factoryDataSize = (uint32_t) __FACTORY_DATA_SIZE; + uint32_t hashId; + uint8_t calculatedHash[SHA256_OUTPUT_SIZE]; + CHIP_ERROR res; + + /* Init mflash */ + status = mflash_drv_init(); + + if (status != kStatus_Success || factoryDataSize > sizeof(factoryDataRamBuffer)) + return CHIP_ERROR_INTERNAL; + + /* Load the factory data into RAM buffer */ + if (mflash_drv_read(factoryDataAddress, (uint32_t *) &factoryDataRamBuffer[0], factoryDataSize) != kStatus_Success) + { + return CHIP_ERROR_INTERNAL; + } + memcpy(&mHeader, factoryDataRamBuffer, sizeof(mHeader)); + if (mHeader.hashId != HASH_ID) + { + return CHIP_FACTORY_DATA_HASH_ID; + } + /* remove the header section */ + memmove(&factoryDataRamBuffer[0], &factoryDataRamBuffer[sizeof(mHeader)], mHeader.size); + + /* Calculate SHA256 value over the factory data and compare with stored value */ + res = Hash_SHA256(&factoryDataRamBuffer[0], mHeader.size, &calculatedHash[0]); + + if (res != CHIP_NO_ERROR) + return res; + + if (memcmp(&calculatedHash[0], &mHeader.hash[0], HASH_LEN) != 0) + { + return CHIP_FACTORY_DATA_HASH_ID; + } + + ChipLogProgress(DeviceLayer, "factory data hash check is successful!"); + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) +{ + CHIP_ERROR res = CHIP_NO_ERROR; + status_t status = STATUS_SUCCESS; + uint8_t el2go_blob[EL2GO_MAX_BLOB_SIZE] = { 0U }; + size_t el2go_blob_size = 0U; + mcuxClEls_EccSignOption_t sign_options = { 0 }; + uint8_t public_key[MCUXCLELS_ECC_PUBLICKEY_SIZE] = { 0 }; + size_t public_key_size = sizeof(public_key); + uint8_t hash[MCUXCLHASH_OUTPUT_SIZE_SHA_256] = { 0 }; + mcuxClEls_KeyIndex_t key_index = MCUXCLELS_KEY_SLOTS; + mcuxClEls_EccByte_t ecc_signature[MCUXCLELS_ECC_SIGNATURE_SIZE]; + uint8_t digest[kSHA256_Hash_Length]; + uint16_t BlobSize = 0; + uint16_t KeyIdSize = 0; + uint32_t Addr; + uint32_t el2go_dac_key_id = 0; + + /* Search key ID FactoryDataId::kEl2GoBlob */ + ReturnErrorOnFailure(SearchForId(FactoryDataId::kEl2GoBlob, NULL, 0, BlobSize, &Addr)); + ReturnErrorOnFailure( + SearchForId(FactoryDataId::kEl2GoDacKeyId, (uint8_t *) &el2go_dac_key_id, sizeof(el2go_dac_key_id), KeyIdSize)); + + /* Calculate message HASH to sign */ + memset(&digest[0], 0, sizeof(digest)); + res = Hash_SHA256(digestToSign.data(), digestToSign.size(), &digest[0]); + if (res != CHIP_NO_ERROR) + { + return res; + } + +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + (void) mcux_els_mutex_lock(); +#endif + + /* Read DAC key from EL2GO data*/ + status = + read_el2go_blob((uint8_t *) Addr, (size_t) BlobSize, el2go_dac_key_id, el2go_blob, EL2GO_MAX_BLOB_SIZE, &el2go_blob_size); + STATUS_SUCCESS_OR_EXIT_MSG("DAC Provate key not found: 0x%08x", status); + + // Import EL2GO blobs in ELS + status = import_el2go_key_in_els(el2go_blob, el2go_blob_size, &key_index); + + // Generate key in ELS + status = els_keygen(key_index, public_key, &public_key_size); + STATUS_SUCCESS_OR_EXIT_MSG("els_keygen failed: 0x%08x", status); + + // Compute signature + status = ELS_sign_hash(hash, ecc_signature, &sign_options, key_index); + CopySpanToMutableSpan(ByteSpan{ ecc_signature, MCUXCLELS_ECC_SIGNATURE_SIZE }, outSignBuffer); + STATUS_SUCCESS_OR_EXIT_MSG("ELS_sign_hash failed: 0x%08x", status); + + status = els_delete_key(key_index); + STATUS_SUCCESS_OR_EXIT_MSG("Deletion of el2goimport_auth failed", status); + +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + (void) mcux_els_mutex_unlock(); +#endif + return CHIP_NO_ERROR; +exit: +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + (void) mcux_els_mutex_unlock(); +#endif + return CHIP_ERROR_INTERNAL; +} + +CHIP_ERROR FactoryDataProviderImpl::Init(void) +{ + uint16_t len; + uint8_t type; + uint16_t keySize = 0; + status_t status = STATUS_SUCCESS; + + ReturnLogErrorOnFailure(ReadAndCheckFactoryDataInFlash()); + + els_enable(); + + return CHIP_NO_ERROR; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.h b/src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.h new file mode 100644 index 0000000000..fdf3aa9b80 --- /dev/null +++ b/src/platform/nxp/rt/rw61x/FactoryDataProviderEl2GoImpl.h @@ -0,0 +1,77 @@ +/* + * + * Copyright (c) 2020-2022 Project CHIP Authors + * Copyright 2024 NXP + * + * 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. + */ + +#pragma once + +#include + +#define FACTORY_DATA_MAX_SIZE 4096 + +#define EL2GO_MAX_BLOB_SIZE 3072U +#define EL2GO_MAX_CERT_SIZE 2048U +#define PUBLIC_KEY_SIZE 64U + +namespace chip { +namespace DeviceLayer { + +/** + * @brief This class provides Commissionable data and Device Attestation Credentials. + * + * This implementation allows to use the ELS hardware module to load the Matter factory + * dataset in RAM at the boot. + * + * + */ + +class FactoryDataProviderImpl : public FactoryDataProvider +{ +public: + static FactoryDataProviderImpl sInstance; + + CHIP_ERROR Init(void); + CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, + uint32_t * contentAddr = NULL); + CHIP_ERROR SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer); + ; + CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override; + +private: + struct Header + { + uint32_t hashId; + uint32_t size; + uint8_t hash[4]; + }; + uint8_t factoryDataRamBuffer[FACTORY_DATA_MAX_SIZE]; + Header mHeader; + + CHIP_ERROR ReadAndCheckFactoryDataInFlash(void); +}; + +inline FactoryDataProvider & FactoryDataPrvd() +{ + return FactoryDataProviderImpl::sInstance; +} + +inline FactoryDataProviderImpl & FactoryDataPrvdImpl() +{ + return FactoryDataProviderImpl::sInstance; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.cpp b/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.cpp index 73155af65e..4fcd61c02d 100644 --- a/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.cpp +++ b/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.cpp @@ -1,7 +1,7 @@ /* * * Copyright (c) 2020-2022 Project CHIP Authors - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,10 @@ extern "C" { #include "ELSFactoryData.h" #include "mflash_drv.h" +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) +#include "els_pkc_mbedtls.h" +#endif /* defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) */ + #include "fsl_adapter_flash.h" /* mbedtls */ @@ -63,6 +67,23 @@ FactoryDataProviderImpl FactoryDataProviderImpl::sInstance; static constexpr size_t kPrivateKeyBlobLength = Crypto::kP256_PrivateKey_Length + ELS_BLOB_METADATA_SIZE + ELS_WRAP_OVERHEAD; +CHIP_ERROR FactoryDataProviderImpl::DecryptAes128Ecb(uint8_t * dest, uint8_t * source, const uint8_t * aes128Key) +{ + uint8_t res = 0; + mbedtls_aes_context aesCtx; + + mbedtls_aes_init(&aesCtx); + res = mbedtls_aes_setkey_dec(&aesCtx, aes128Key, 128U); + VerifyOrReturnError(res == 0, CHIP_ERROR_INTERNAL); + + res = mbedtls_aes_crypt_ecb(&aesCtx, MBEDTLS_AES_DECRYPT, source, dest); + VerifyOrReturnError(res == 0, CHIP_ERROR_INTERNAL); + + mbedtls_aes_free(&aesCtx); + + return CHIP_NO_ERROR; +} + CHIP_ERROR FactoryDataProviderImpl::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * contentAddr) { @@ -123,6 +144,7 @@ CHIP_ERROR FactoryDataProviderImpl::SearchForId(uint8_t searchedType, uint8_t * CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer) { + CHIP_ERROR res = CHIP_NO_ERROR; uint8_t els_key_blob[kPrivateKeyBlobLength]; size_t els_key_blob_size = sizeof(els_key_blob); uint16_t keySize = 0; @@ -146,6 +168,19 @@ CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign PLOG_DEBUG_BUFFER("els_key_blob", els_key_blob, els_key_blob_size); + /* Calculate message HASH to sign */ + memset(&digest[0], 0, sizeof(digest)); + res = Hash_SHA256(digestToSign.data(), digestToSign.size(), &digest[0]); + if (res != CHIP_NO_ERROR) + { + return res; + } + + PLOG_DEBUG_BUFFER("digestToSign", digestToSign.data(), digestToSign.size()); + +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + (void) mcux_els_mutex_lock(); +#endif /* Import blob DAC key into SE50 (reserved key slot) */ status = import_die_int_wrapped_key_into_els(els_key_blob, els_key_blob_size, plain_key_properties, &key_index); STATUS_SUCCESS_OR_EXIT_MSG("import_die_int_wrapped_key_into_els failed: 0x%08x", status); @@ -160,12 +195,6 @@ CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign /* The key is usable for signing. */ PLOG_DEBUG_BUFFER("public_key", public_key, public_key_size); - /* Calculate message HASH to sign */ - memset(&digest[0], 0, sizeof(digest)); - ReturnErrorOnFailure(Hash_SHA256(digestToSign.data(), digestToSign.size(), &digest[0])); - - PLOG_DEBUG_BUFFER("digestToSign", digestToSign.data(), digestToSign.size()); - /* ECC sign message hash with the key index slot reserved during the blob importation */ ELS_sign_hash(digest, ecc_signature, &sign_options, key_index); @@ -173,10 +202,16 @@ CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & digestToSign els_delete_key(key_index); /* Generate MutableByteSpan with ECC signature and ECC signature size */ +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + (void) mcux_els_mutex_unlock(); +#endif return CopySpanToMutableSpan(ByteSpan{ ecc_signature, MCUXCLELS_ECC_SIGNATURE_SIZE }, outSignBuffer); exit: els_delete_key(key_index); +#if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) + (void) mcux_els_mutex_unlock(); +#endif return CHIP_ERROR_INVALID_SIGNATURE; } @@ -188,6 +223,7 @@ CHIP_ERROR FactoryDataProviderImpl::ReadAndCheckFactoryDataInFlash(void) uint32_t hashId; uint8_t calculatedHash[SHA256_OUTPUT_SIZE]; CHIP_ERROR res; + uint8_t currentBlock[16]; /* Init mflash */ status = mflash_drv_init(); @@ -216,13 +252,64 @@ CHIP_ERROR FactoryDataProviderImpl::ReadAndCheckFactoryDataInFlash(void) if (memcmp(&calculatedHash[0], &mHeader.hash[0], HASH_LEN) != 0) { - return CHIP_ERROR_NOT_FOUND; + /* HASH value didn't match, test if factory data are encrypted */ + + /* try to decrypt factory data, reset factory data buffer content*/ + memset(factoryDataRamBuffer, 0, sizeof(factoryDataRamBuffer)); + memset(calculatedHash, 0, sizeof(calculatedHash)); + + factoryDataAddress += sizeof(Header); + + /* Load the buffer into RAM by reading each 16 bytes blocks */ + for (int i = 0; i < (mHeader.size / 16); i++) + { + if (mflash_drv_read(factoryDataAddress + i * 16, (uint32_t *) ¤tBlock[0], sizeof(currentBlock)) != + kStatus_Success) + { + return CHIP_ERROR_INTERNAL; + } + ReturnErrorOnFailure(DecryptAes128Ecb(&factoryDataRamBuffer[i * 16], ¤tBlock[0], pAesKey)); + } + + /* Calculate SHA256 value over the factory data and compare with stored value */ + res = Hash_SHA256(&factoryDataRamBuffer[0], mHeader.size, &calculatedHash[0]); + if (memcmp(&calculatedHash[0], &mHeader.hash[0], HASH_LEN) != 0) + { + return CHIP_ERROR_NOT_FOUND; + } } ChipLogProgress(DeviceLayer, "factory data hash check is successful!"); return CHIP_NO_ERROR; } +CHIP_ERROR FactoryDataProviderImpl::SetAes128Key(const uint8_t * keyAes128) +{ + CHIP_ERROR error = CHIP_ERROR_INVALID_ARGUMENT; + if (keyAes128 != nullptr) + { + pAesKey = keyAes128; + error = CHIP_NO_ERROR; + } + return error; +} + +CHIP_ERROR FactoryDataProviderImpl::SetEncryptionMode(EncryptionMode mode) +{ + CHIP_ERROR error = CHIP_ERROR_INVALID_ARGUMENT; + + /* + * Currently the fwk_factory_data_provider module supports only ecb mode. + * Therefore return an error if encrypt mode is not ecb + */ + if (mode == encrypt_ecb) + { + encryptMode = mode; + error = CHIP_NO_ERROR; + } + return error; +} + CHIP_ERROR FactoryDataProviderImpl::Init(void) { uint16_t len; @@ -250,11 +337,6 @@ CHIP_ERROR FactoryDataProviderImpl::Init(void) ChipLogProgress(DeviceLayer, "SSS: convert DAC private key to blob"); ReturnLogErrorOnFailure(ELS_ConvertDacKey()); ChipLogProgress(DeviceLayer, "System restarting"); - // Restart the system. - NVIC_SystemReset(); - while (1) - { - } } return CHIP_NO_ERROR; @@ -278,8 +360,8 @@ CHIP_ERROR FactoryDataProviderImpl::ELS_ConvertDacKey() PLOG_DEBUG_BUFFER("blob", blob, blobSize); /* Read all factory data */ - hal_flash_status_t status = - HAL_FlashRead(factoryDataAddress + MFLASH_BASE_ADDRESS, newSize - (ELS_BLOB_METADATA_SIZE + ELS_WRAP_OVERHEAD), data); + hal_flash_status_t status = HAL_FlashRead(factoryDataAddress + MFLASH_BASE_ADDRESS, sizeof(Header), data); + memcpy(data + sizeof(Header), factoryDataRamBuffer, mHeader.size); VerifyOrReturnError(status == kStatus_HAL_Flash_Success, CHIP_ERROR_INTERNAL); ChipLogError(DeviceLayer, "SSS: cached factory data in RAM"); @@ -296,6 +378,13 @@ CHIP_ERROR FactoryDataProviderImpl::ELS_ConvertDacKey() VerifyOrReturnError(status == kStatus_HAL_Flash_Success, CHIP_ERROR_INTERNAL); ChipLogError(DeviceLayer, "SSS: updated factory data"); + /* remove the header section as it will no longer be used */ + memmove(&data[0], &data[sizeof(mHeader)], newSize); + memset(factoryDataRamBuffer, 0, sizeof(factoryDataRamBuffer)); + memcpy(factoryDataRamBuffer, data, newSize); + /* Actualisation of the factory data payload size */ + mHeader.size = newSize; + chip::Platform::MemoryFree(data); return CHIP_NO_ERROR; } diff --git a/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.h b/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.h index 4fc4785328..4e72fcd953 100644 --- a/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.h +++ b/src/platform/nxp/rt/rw61x/FactoryDataProviderImpl.h @@ -1,7 +1,7 @@ /* * * Copyright (c) 2020-2022 Project CHIP Authors - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,9 @@ class FactoryDataProviderImpl : public FactoryDataProvider uint32_t * contentAddr = NULL); CHIP_ERROR SignWithDacKey(const ByteSpan & digestToSign, MutableByteSpan & outSignBuffer); + CHIP_ERROR SetAes128Key(const uint8_t * keyAes128); + CHIP_ERROR SetEncryptionMode(EncryptionMode mode); + private: struct Header { @@ -54,6 +57,9 @@ class FactoryDataProviderImpl : public FactoryDataProvider uint8_t factoryDataRamBuffer[FACTORY_DATA_MAX_SIZE]; Header mHeader; + const uint8_t * pAesKey = nullptr; + EncryptionMode encryptMode = encrypt_ecb; + /* TLV offset */ static constexpr uint32_t kLengthOffset = 1; static constexpr uint32_t kValueOffset = 3; @@ -61,6 +67,7 @@ class FactoryDataProviderImpl : public FactoryDataProvider CHIP_ERROR ReplaceWithBlob(uint8_t * data, uint8_t * blob, size_t blobLen, uint32_t offset); CHIP_ERROR ELS_ExportBlob(uint8_t * data, size_t * dataLen, uint32_t & offset); CHIP_ERROR ELS_ConvertDacKey(); + CHIP_ERROR DecryptAes128Ecb(uint8_t * dest, uint8_t * source, const uint8_t * aes128Key); CHIP_ERROR ReadAndCheckFactoryDataInFlash(void); }; diff --git a/third_party/nxp/nxp_matter_support b/third_party/nxp/nxp_matter_support index 69f40517ca..7323d61dfc 160000 --- a/third_party/nxp/nxp_matter_support +++ b/third_party/nxp/nxp_matter_support @@ -1 +1 @@ -Subproject commit 69f40517ca5f27fdf3026f695c0d0607b604dc0e +Subproject commit 7323d61dfc746aff677cb40c17cfed9d43dd9c1d From dee82ef764576aef07ad18b59486b7604c44d936 Mon Sep 17 00:00:00 2001 From: Amine Alami <43780877+Alami-Amine@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:45:18 +0100 Subject: [PATCH 094/219] Make IsInitialized implementation in OpenSSL backward compatible with older OpenSSL versions (#36634) --- src/crypto/CHIPCryptoPALOpenSSL.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/crypto/CHIPCryptoPALOpenSSL.cpp b/src/crypto/CHIPCryptoPALOpenSSL.cpp index e1a8acb55f..9f2592a12a 100644 --- a/src/crypto/CHIPCryptoPALOpenSSL.cpp +++ b/src/crypto/CHIPCryptoPALOpenSSL.cpp @@ -479,11 +479,13 @@ bool Hash_SHA256_stream::IsInitialized() EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext); VerifyOrReturnValue(mdctx != nullptr, false); -// Verify that the EVP_MD_CTX is initialized to SHA256 (ensures that EVP_DigestInit_ex was called) -#if CHIP_CRYPTO_BORINGSSL +// Verify that the EVP_MD_CTX is initialized to SHA256 (ensures that EVP_DigestInit_ex was successfully called). +// The legacy API EVP_MD_CTX_md() to check SHA256 initialization is deprecated in OpenSSL 3.0 +// and was replaced by EVP_MD_CTX_get0_md(). +// OpenSSL 1.1.1, which BoringSSL also uses at the time of this comment, does not support the newer replacement API. +#if CHIP_CRYPTO_BORINGSSL || (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x30000000L) return EVP_MD_CTX_md(mdctx) == _digestForType(DigestType::SHA256); #else - // EVP_MD_CTX_md() was Deprecated in OPENSSL 3.0; However, BoringSSL does not support EVP_MD_CTX_get0_md() yet return EVP_MD_CTX_get0_md(mdctx) == _digestForType(DigestType::SHA256); #endif } From e75d6da10bfcd7bab7d4e99529bdd30b43420114 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 26 Nov 2024 15:07:59 -0500 Subject: [PATCH 095/219] Add some additional `dataModelProvider` settings on server init (#36639) * Add some missed registrations of dataModelProvider in server init * Fix commissioner main dependencies (make nrf tests compile) * Move around dependencies - apparently the commissioner main should be public * Fix one more odd dependency --- examples/common/tracing/BUILD.gn | 2 +- examples/lighting-app/nrfconnect/main/AppTask.cpp | 2 ++ examples/lighting-app/qpg/src/AppTask.cpp | 2 ++ examples/ota-requestor-app/ameba/main/chipinterface.cpp | 4 +++- examples/platform/linux/BUILD.gn | 3 +-- 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/common/tracing/BUILD.gn b/examples/common/tracing/BUILD.gn index 9a11930600..6e3bb1277a 100644 --- a/examples/common/tracing/BUILD.gn +++ b/examples/common/tracing/BUILD.gn @@ -79,7 +79,6 @@ source_set("trace_handlers") { source_set("trace_handlers_decoder") { sources = [ "TraceDecoder.cpp", - "TraceHandlers.cpp", "decoder/TraceDecoderProtocols.cpp", "decoder/bdx/Decoder.cpp", "decoder/echo/Decoder.cpp", @@ -94,6 +93,7 @@ source_set("trace_handlers_decoder") { public_configs = [ ":default_config" ] deps = [ + ":trace_handlers", "${chip_root}/src/lib", "${chip_root}/src/lib/core:types", ] diff --git a/examples/lighting-app/nrfconnect/main/AppTask.cpp b/examples/lighting-app/nrfconnect/main/AppTask.cpp index 014849780c..b8464779d7 100644 --- a/examples/lighting-app/nrfconnect/main/AppTask.cpp +++ b/examples/lighting-app/nrfconnect/main/AppTask.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -262,6 +263,7 @@ CHIP_ERROR AppTask::Init() initParams.operationalKeystore = &sPSAOperationalKeystore; #endif (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; ReturnErrorOnFailure(chip::Server::GetInstance().Init(initParams)); AppFabricTableDelegate::Init(); diff --git a/examples/lighting-app/qpg/src/AppTask.cpp b/examples/lighting-app/qpg/src/AppTask.cpp index 0c09e97a6a..1047968ffe 100644 --- a/examples/lighting-app/qpg/src/AppTask.cpp +++ b/examples/lighting-app/qpg/src/AppTask.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -273,6 +274,7 @@ void AppTask::InitServer(intptr_t arg) VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR); VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sFaultTestEventTriggerHandler) == CHIP_NO_ERROR); (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.dataModelProvider = CodegenDataModelProviderInstance(); initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate; chip::Server::GetInstance().Init(initParams); diff --git a/examples/ota-requestor-app/ameba/main/chipinterface.cpp b/examples/ota-requestor-app/ameba/main/chipinterface.cpp index 6d0af83d5c..115441a2f9 100644 --- a/examples/ota-requestor-app/ameba/main/chipinterface.cpp +++ b/examples/ota-requestor-app/ameba/main/chipinterface.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -78,7 +79,8 @@ static void InitServer(intptr_t context) static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); static AmebaObserver sAmebaObserver; - initParams.appDelegate = &sAmebaObserver; + initParams.dataModelProvider = CodegenDataModelProviderInstance(); + initParams.appDelegate = &sAmebaObserver; chip::Server::GetInstance().Init(initParams); gExampleDeviceInfoProvider.SetStorageDelegate(&Server::GetInstance().GetPersistentStorage()); chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 1d4f191cb8..478b9960cd 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -74,8 +74,6 @@ source_set("app-main") { "AppMain.h", "CommissionableInit.cpp", "CommissionableInit.h", - "CommissionerMain.cpp", - "CommissionerMain.h", "LinuxCommissionableDataProvider.cpp", "LinuxCommissionableDataProvider.h", "NamedPipeCommands.cpp", @@ -90,6 +88,7 @@ source_set("app-main") { public_deps = [ ":boolean-state-configuration-test-event-trigger", + ":commissioner-main", ":device-energy-management-test-event-trigger", ":energy-evse-test-event-trigger", ":energy-reporting-test-event-trigger", From ffbc362200b60380114a3e136a44343c0de5e64d Mon Sep 17 00:00:00 2001 From: Karsten Sperling <113487422+ksperling-apple@users.noreply.github.com> Date: Wed, 27 Nov 2024 10:23:34 +1300 Subject: [PATCH 096/219] Resolve CommissionerMain dependency issues (#36632) * Resolve CommissionerMain dependency issues Note that CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE=1 requires chip_build_controller=true at the GN level, otherwise `lib` does not pull in `controller`. * Touch something in /tests/ to force NRF native_posix_64 tests to run * Add nogncheck to conditional controller imports --- examples/platform/linux/CommissionerMain.cpp | 20 ++++++++--------- examples/platform/linux/CommissionerMain.h | 23 ++++++++------------ src/app/tests/BUILD.gn | 7 +++--- 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/examples/platform/linux/CommissionerMain.cpp b/examples/platform/linux/CommissionerMain.cpp index 54ad104c01..f54cfc4bd1 100644 --- a/examples/platform/linux/CommissionerMain.cpp +++ b/examples/platform/linux/CommissionerMain.cpp @@ -16,10 +16,7 @@ * limitations under the License. */ -#include -#include - -#include +#include "CommissionerMain.h" #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE @@ -31,6 +28,7 @@ #include #include #include +#include #include #include @@ -48,23 +46,23 @@ #include #include +#include #include #include #include +#include +#include #include -#include -#include -#include -#include +#include // nogncheck +#include // nogncheck #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED #include "TraceHandlers.h" #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED #include - -#include "CommissionerMain.h" +#include using namespace chip; using namespace chip::Credentials; @@ -459,7 +457,7 @@ CommissionerDiscoveryController * GetCommissionerDiscoveryController() return &gCommissionerDiscoveryController; } -SessionKeystore * GetSessionKeystore() +Crypto::SessionKeystore * GetSessionKeystore() { return &gSessionKeystore; } diff --git a/examples/platform/linux/CommissionerMain.h b/examples/platform/linux/CommissionerMain.h index 106e94b0ed..64855b5570 100644 --- a/examples/platform/linux/CommissionerMain.h +++ b/examples/platform/linux/CommissionerMain.h @@ -18,20 +18,15 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include +#include #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE -using chip::PersistentStorageDelegate; -using chip::Controller::DeviceCommissioner; -using chip::Crypto::SessionKeystore; -using chip::Transport::PeerAddress; +#include // nogncheck +#include +#include +#include +#include CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, PeerAddress address); CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index); @@ -39,9 +34,9 @@ CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index); CHIP_ERROR InitCommissioner(uint16_t commissionerPort, uint16_t udcListenPort, chip::FabricId fabricId = chip::kUndefinedFabricId); void ShutdownCommissioner(); -DeviceCommissioner * GetDeviceCommissioner(); +chip::Controller::DeviceCommissioner * GetDeviceCommissioner(); CommissionerDiscoveryController * GetCommissionerDiscoveryController(); -SessionKeystore * GetSessionKeystore(); -PersistentStorageDelegate * GetPersistentStorageDelegate(); +chip::Crypto::SessionKeystore * GetSessionKeystore(); +chip::PersistentStorageDelegate * GetPersistentStorageDelegate(); #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 105d09f7ad..18856d40a1 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -305,10 +305,9 @@ chip_test_suite("tests") { test_sources += [ "TestClusterStateCache.cpp" ] } - # On NRF, Open IoT SDK and fake platforms we do not have a realtime clock available, so - # TestEventLogging.cpp would be testing the same thing as - # TestEventLoggingNoUTCTime, but it's not set up to deal with the timestamps - # being that low. + # On NRF, Open IoT SDK and fake platforms we do not have a realtime clock available, + # so TestEventLogging.cpp would be testing the same thing as TestEventLoggingNoUTCTime, + # but it's not set up to deal with the timestamps being that low. if (chip_device_platform != "nrfconnect" && chip_device_platform != "openiotsdk" && chip_device_platform != "fake") { test_sources += [ "TestEventLogging.cpp" ] From 63182c41e71bbbe29ca4ce8fc11c5723f52245aa Mon Sep 17 00:00:00 2001 From: Shubham Patil Date: Wed, 27 Nov 2024 12:32:02 +0530 Subject: [PATCH 097/219] dac_revocation: Perform cross validation against crl signer or crl signer delegator (#35144) * dac_revocation: Support crl signer and crl signer delegator - Add crl signer and crl signer delegator cert in the python script which generates the revocation set - perform the cross validation of DAC/PAI with crl signer and crl signer delegator cert - Extended and added unit tests for crl signer delegator case * include algoright and remove the local var declaration * use unused attribute * Fix the buffer overrun and use maybe_unused instead of unused attribute * we do not need to differentiate pai/dac when cross verifying * add checks on return value and unit tests on malformed crl signer cert * use std::string instead of const char * * address some more reviews * Update src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp Co-authored-by: Boris Zbarsky --------- Co-authored-by: Boris Zbarsky --- .../TestDACRevocationDelegateImpl.cpp | 175 ++++++++++++++++-- .../TestDACRevocationDelegateImpl.h | 13 ++ .../TestDeviceAttestationCredentials.cpp | 66 ++++++- 3 files changed, 231 insertions(+), 23 deletions(-) diff --git a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp index 0db0337219..0ad7de13e8 100644 --- a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp +++ b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -30,6 +31,9 @@ namespace chip { namespace Credentials { namespace { + +static constexpr uint32_t kMaxIssuerBase64Len = BASE64_ENCODED_LEN(kMaxCertificateDistinguishedNameLength); + CHIP_ERROR BytesToHexStr(const ByteSpan & bytes, MutableCharSpan & outHexStr) { Encoding::HexFlags flags = Encoding::HexFlags::kUppercase; @@ -37,6 +41,42 @@ CHIP_ERROR BytesToHexStr(const ByteSpan & bytes, MutableCharSpan & outHexStr) outHexStr.reduce_size(2 * bytes.size()); return CHIP_NO_ERROR; } + +CHIP_ERROR X509_PemToDer(const std::string & pemCert, MutableByteSpan & derCert) +{ + std::string beginMarker = "-----BEGIN CERTIFICATE-----"; + std::string endMarker = "-----END CERTIFICATE-----"; + + std::size_t beginPos = pemCert.find(beginMarker); + VerifyOrReturnError(beginPos != std::string::npos, CHIP_ERROR_INVALID_ARGUMENT); + + std::size_t endPos = pemCert.find(endMarker); + VerifyOrReturnError(endPos != std::string::npos, CHIP_ERROR_INVALID_ARGUMENT); + + VerifyOrReturnError(beginPos < endPos, CHIP_ERROR_INVALID_ARGUMENT); + + // Extract content between markers + std::string plainB64Str = pemCert.substr(beginPos + beginMarker.length(), endPos - (beginPos + beginMarker.length())); + + // Remove all newline characters '\n' and '\r' + plainB64Str.erase(std::remove(plainB64Str.begin(), plainB64Str.end(), '\n'), plainB64Str.end()); + plainB64Str.erase(std::remove(plainB64Str.begin(), plainB64Str.end(), '\r'), plainB64Str.end()); + + VerifyOrReturnError(!plainB64Str.empty(), CHIP_ERROR_INVALID_ARGUMENT); + + // Verify we have enough room to store the decoded certificate + size_t maxDecodeLen = BASE64_MAX_DECODED_LEN(plainB64Str.size()); + VerifyOrReturnError(derCert.size() >= maxDecodeLen, CHIP_ERROR_BUFFER_TOO_SMALL); + + // decode b64 + uint16_t derLen = Base64Decode(plainB64Str.c_str(), static_cast(plainB64Str.size()), derCert.data()); + VerifyOrReturnError(derLen != UINT16_MAX, CHIP_ERROR_INVALID_ARGUMENT); + + derCert.reduce_size(derLen); + + return CHIP_NO_ERROR; +} + } // anonymous namespace CHIP_ERROR TestDACRevocationDelegateImpl::SetDeviceAttestationRevocationSetPath(std::string_view path) @@ -52,6 +92,58 @@ void TestDACRevocationDelegateImpl::ClearDeviceAttestationRevocationSetPath() mDeviceAttestationRevocationSetPath = mDeviceAttestationRevocationSetPath.substr(0, 0); } +// outSubject is subject encoded as base64 string +// outKeyId is SKID encoded as hex string +CHIP_ERROR TestDACRevocationDelegateImpl::GetSubjectAndKeyIdFromPEMCert(const std::string & certPEM, std::string & outSubject, + std::string & outKeyId) +{ + // buffers and spans for storing crl signer delegator OR crl signer cert info + char subjectBuf[kMaxIssuerBase64Len] = { 0 }; + char skidBuf[2 * kAuthorityKeyIdentifierLength] = { 0 }; + uint8_t certDerBuf[kMax_x509_Certificate_Length] = { 0 }; + + MutableCharSpan subject(subjectBuf); + MutableCharSpan keyId(skidBuf); + MutableByteSpan certDER(certDerBuf); + + ReturnLogErrorOnFailure(X509_PemToDer(certPEM, certDER)); + ReturnErrorOnFailure(GetSubjectNameBase64Str(certDER, subject)); + ReturnErrorOnFailure(GetSKIDHexStr(certDER, keyId)); + + outSubject = std::string(subject.data(), subject.size()); + outKeyId = std::string(keyId.data(), keyId.size()); + + return CHIP_NO_ERROR; +} + +// Check if issuer and AKID matches with the crl signer OR crl signer delegator's subject and SKID +bool TestDACRevocationDelegateImpl::CrossValidateCert(const Json::Value & revokedSet, const std::string & akidHexStr, + const std::string & issuerNameBase64Str) +{ + std::string certPEM; + [[maybe_unused]] std::string certType; + + if (revokedSet.isMember("crl_signer_delegator")) + { + certPEM = revokedSet["crl_signer_delegator"].asString(); + certType = "CRL Signer delegator"; + } + else + { + certPEM = revokedSet["crl_signer_cert"].asString(); + certType = "CRL Signer"; + } + + std::string subject; // crl signer or crl signer delegator subject + std::string keyId; // crl signer or crl signer delegator SKID + VerifyOrReturnValue(CHIP_NO_ERROR == GetSubjectAndKeyIdFromPEMCert(certPEM, subject, keyId), false); + + ChipLogDetail(NotSpecified, "%s: Subject: %s", certType.c_str(), subject.c_str()); + ChipLogDetail(NotSpecified, "%s: SKID: %s", certType.c_str(), keyId.c_str()); + + return (akidHexStr == keyId && issuerNameBase64Str == subject); +} + // This method parses the below JSON Scheme // [ // { @@ -62,6 +154,8 @@ void TestDACRevocationDelegateImpl::ClearDeviceAttestationRevocationSetPath() // "serial1 bytes as base64", // "serial2 bytes as base64" // ] +// "crl_signer_cert": "", +// "crl_signer_delegator": , // } // ] // @@ -95,6 +189,7 @@ bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const CharSpan & akid std::string serialNumber = std::string(serialNumberHexStr.data(), serialNumberHexStr.size()); std::string akid = std::string(akidHexStr.data(), akidHexStr.size()); + // 6.2.4.2. Determining Revocation Status of an Entity for (const auto & revokedSet : jsonData) { if (revokedSet["issuer_name"].asString() != issuerName) @@ -105,6 +200,12 @@ bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const CharSpan & akid { continue; } + + // 4.a cross validate PAI with crl signer OR crl signer delegator + // 4.b cross validate DAC with crl signer OR crl signer delegator + VerifyOrReturnValue(CrossValidateCert(revokedSet, akid, issuerName), false); + + // 4.c check if serial number is revoked for (const auto & revokedSerialNumber : revokedSet["revoked_serial_numbers"]) { if (revokedSerialNumber.asString() == serialNumber) @@ -116,14 +217,33 @@ bool TestDACRevocationDelegateImpl::IsEntryInRevocationSet(const CharSpan & akid return false; } -CHIP_ERROR TestDACRevocationDelegateImpl::GetAKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outAKIDHexStr) +CHIP_ERROR TestDACRevocationDelegateImpl::GetKeyIDHexStr(const ByteSpan & certDer, MutableCharSpan & outKeyIDHexStr, bool isAKID) { - uint8_t akidBuf[kAuthorityKeyIdentifierLength]; - MutableByteSpan akid(akidBuf); + static_assert(kAuthorityKeyIdentifierLength == kSubjectKeyIdentifierLength, "AKID and SKID length mismatch"); + + uint8_t keyIdBuf[kAuthorityKeyIdentifierLength]; + MutableByteSpan keyId(keyIdBuf); - ReturnErrorOnFailure(ExtractAKIDFromX509Cert(certDer, akid)); + if (isAKID) + { + ReturnErrorOnFailure(ExtractAKIDFromX509Cert(certDer, keyId)); + } + else + { + ReturnErrorOnFailure(ExtractSKIDFromX509Cert(certDer, keyId)); + } - return BytesToHexStr(akid, outAKIDHexStr); + return BytesToHexStr(keyId, outKeyIDHexStr); +} + +CHIP_ERROR TestDACRevocationDelegateImpl::GetAKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outAKIDHexStr) +{ + return GetKeyIDHexStr(certDer, outAKIDHexStr, true); +} + +CHIP_ERROR TestDACRevocationDelegateImpl::GetSKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outSKIDHexStr) +{ + return GetKeyIDHexStr(certDer, outSKIDHexStr, false /* isAKID */); } CHIP_ERROR TestDACRevocationDelegateImpl::GetSerialNumberHexStr(const ByteSpan & certDer, MutableCharSpan & outSerialNumberHexStr) @@ -135,25 +255,44 @@ CHIP_ERROR TestDACRevocationDelegateImpl::GetSerialNumberHexStr(const ByteSpan & return BytesToHexStr(serialNumber, outSerialNumberHexStr); } -CHIP_ERROR TestDACRevocationDelegateImpl::GetIssuerNameBase64Str(const ByteSpan & certDer, - MutableCharSpan & outIssuerNameBase64String) +CHIP_ERROR TestDACRevocationDelegateImpl::GetRDNBase64Str(const ByteSpan & certDer, MutableCharSpan & outRDNBase64String, + bool isIssuer) { - uint8_t issuerBuf[kMaxCertificateDistinguishedNameLength] = { 0 }; - MutableByteSpan issuer(issuerBuf); + uint8_t rdnBuf[kMaxCertificateDistinguishedNameLength] = { 0 }; + MutableByteSpan rdn(rdnBuf); - ReturnErrorOnFailure(ExtractIssuerFromX509Cert(certDer, issuer)); - VerifyOrReturnError(outIssuerNameBase64String.size() >= BASE64_ENCODED_LEN(issuer.size()), CHIP_ERROR_BUFFER_TOO_SMALL); + if (isIssuer) + { + ReturnErrorOnFailure(ExtractIssuerFromX509Cert(certDer, rdn)); + } + else + { + ReturnErrorOnFailure(ExtractSubjectFromX509Cert(certDer, rdn)); + } - uint16_t encodedLen = Base64Encode(issuer.data(), static_cast(issuer.size()), outIssuerNameBase64String.data()); - outIssuerNameBase64String.reduce_size(encodedLen); + VerifyOrReturnError(outRDNBase64String.size() >= BASE64_ENCODED_LEN(rdn.size()), CHIP_ERROR_BUFFER_TOO_SMALL); + + uint16_t encodedLen = Base64Encode(rdn.data(), static_cast(rdn.size()), outRDNBase64String.data()); + outRDNBase64String.reduce_size(encodedLen); return CHIP_NO_ERROR; } -bool TestDACRevocationDelegateImpl::IsCertificateRevoked(const ByteSpan & certDer) +CHIP_ERROR TestDACRevocationDelegateImpl::GetIssuerNameBase64Str(const ByteSpan & certDer, + MutableCharSpan & outIssuerNameBase64String) { - static constexpr uint32_t maxIssuerBase64Len = BASE64_ENCODED_LEN(kMaxCertificateDistinguishedNameLength); + return GetRDNBase64Str(certDer, outIssuerNameBase64String, true /* isIssuer */); +} + +CHIP_ERROR TestDACRevocationDelegateImpl::GetSubjectNameBase64Str(const ByteSpan & certDer, + MutableCharSpan & outSubjectNameBase64String) +{ + return GetRDNBase64Str(certDer, outSubjectNameBase64String, false /* isIssuer */); +} - char issuerNameBuffer[maxIssuerBase64Len] = { 0 }; +// @param certDer Certificate, in DER format, to check for revocation +bool TestDACRevocationDelegateImpl::IsCertificateRevoked(const ByteSpan & certDer) +{ + char issuerNameBuffer[kMaxIssuerBase64Len] = { 0 }; char serialNumberHexStrBuffer[2 * kMaxCertificateSerialNumberLength] = { 0 }; char akidHexStrBuffer[2 * kAuthorityKeyIdentifierLength] = { 0 }; @@ -170,8 +309,6 @@ bool TestDACRevocationDelegateImpl::IsCertificateRevoked(const ByteSpan & certDe VerifyOrReturnValue(CHIP_NO_ERROR == GetAKIDHexStr(certDer, akid), false); ChipLogDetail(NotSpecified, "AKID: %.*s", static_cast(akid.size()), akid.data()); - // TODO: Cross-validate the CRLSignerCertificate and CRLSignerDelegator per spec: #34587 - return IsEntryInRevocationSet(akid, issuerName, serialNumber); } @@ -183,8 +320,8 @@ void TestDACRevocationDelegateImpl::CheckForRevokedDACChain( if (mDeviceAttestationRevocationSetPath.empty()) { - onCompletion->mCall(onCompletion->mContext, info, attestationError); + return; } ChipLogDetail(NotSpecified, "Checking for revoked DAC in %s", mDeviceAttestationRevocationSetPath.c_str()); diff --git a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h index 2dc169c2b6..ac1208dbca 100644 --- a/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h +++ b/src/credentials/attestation_verifier/TestDACRevocationDelegateImpl.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include @@ -52,11 +53,23 @@ class TestDACRevocationDelegateImpl : public DeviceAttestationRevocationDelegate void ClearDeviceAttestationRevocationSetPath(); private: + bool CrossValidateCert(const Json::Value & revokedSet, const std::string & akIdHexStr, const std::string & issuerNameBase64Str); + + CHIP_ERROR GetKeyIDHexStr(const ByteSpan & certDer, MutableCharSpan & outKeyIDHexStr, bool isAKID); CHIP_ERROR GetAKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outAKIDHexStr); + CHIP_ERROR GetSKIDHexStr(const ByteSpan & certDer, MutableCharSpan & outSKIDHexStr); + CHIP_ERROR GetSerialNumberHexStr(const ByteSpan & certDer, MutableCharSpan & outSerialNumberHexStr); + + CHIP_ERROR GetRDNBase64Str(const ByteSpan & certDer, MutableCharSpan & outRDNBase64String, bool isIssuer); CHIP_ERROR GetIssuerNameBase64Str(const ByteSpan & certDer, MutableCharSpan & outIssuerNameBase64String); + CHIP_ERROR GetSubjectNameBase64Str(const ByteSpan & certDer, MutableCharSpan & outSubjectNameBase64String); + + CHIP_ERROR GetSubjectAndKeyIdFromPEMCert(const std::string & certPEM, std::string & outSubject, std::string & outKeyId); + bool IsEntryInRevocationSet(const CharSpan & akidHexStr, const CharSpan & issuerNameBase64Str, const CharSpan & serialNumberHexStr); + bool IsCertificateRevoked(const ByteSpan & certDer); std::string mDeviceAttestationRevocationSetPath; diff --git a/src/credentials/tests/TestDeviceAttestationCredentials.cpp b/src/credentials/tests/TestDeviceAttestationCredentials.cpp index 0f80df9fa9..95eb51ce77 100644 --- a/src/credentials/tests/TestDeviceAttestationCredentials.cpp +++ b/src/credentials/tests/TestDeviceAttestationCredentials.cpp @@ -468,12 +468,13 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); - // Test DAC is revoked + // Test DAC is revoked, crl signer is PAI itself const char * jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; @@ -481,12 +482,13 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kDacRevoked); - // Test PAI is revoked + // Test PAI is revoked, crl signer is PAA itself jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "6AFD22771F511FECBF1641976710DCDC31A1717E", "issuer_name": "MDAxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQTEUMBIGCisGAQQBgqJ8AgEMBEZGRjE=", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIBvTCCAWSgAwIBAgIITqjoMYLUHBwwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowMDEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABLbLY3KIfyko9brIGqnZOuJDHK2p154kL2UXfvnO2TKijs0Duq9qj8oYShpQ\nNUKWDUU/MD8fGUIddR6Pjxqam3WjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAfBgNV\nHSMEGDAWgBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAKBggqhkjOPQQDAgNHADBEAiBQ\nqoAC9NkyqaAFOPZTaK0P/8jvu8m+t9pWmDXPmqdRDgIgI7rI/g8j51RFtlM5CBpH\nmUkpxyqvChVI1A0DTVFLJd4=\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["3E6CE6509AD840CD"] }] )"; @@ -494,18 +496,20 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kPaiRevoked); - // Test DAC and PAI both revoked + // Test DAC and PAI both revoked, crl signers are PAI and PAA respectively jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["0C694F7F866067B2"] }, { "type": "revocation_set", "issuer_subject_key_id": "6AFD22771F511FECBF1641976710DCDC31A1717E", "issuer_name": "MDAxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQTEUMBIGCisGAQQBgqJ8AgEMBEZGRjE=", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIBvTCCAWSgAwIBAgIITqjoMYLUHBwwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowMDEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABLbLY3KIfyko9brIGqnZOuJDHK2p154kL2UXfvnO2TKijs0Duq9qj8oYShpQ\nNUKWDUU/MD8fGUIddR6Pjxqam3WjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAfBgNV\nHSMEGDAWgBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAKBggqhkjOPQQDAgNHADBEAiBQ\nqoAC9NkyqaAFOPZTaK0P/8jvu8m+t9pWmDXPmqdRDgIgI7rI/g8j51RFtlM5CBpH\nmUkpxyqvChVI1A0DTVFLJd4=\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["3E6CE6509AD840CD"] }] )"; @@ -522,11 +526,13 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test issuer does not match + // crl_signer_cert is not valid and just used for testing jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "BF42B7094DEBD515EC6ECF33B81115225F325289", "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIBvTCCAWSgAwIBAgIITqjoMYLUHBwwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowMDEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABLbLY3KIfyko9brIGqnZOuJDHK2p154kL2UXfvnO2TKijs0Duq9qj8oYShpQ\nNUKWDUU/MD8fGUIddR6Pjxqam3WjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAfBgNV\nHSMEGDAWgBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAKBggqhkjOPQQDAgNHADBEAiBQ\nqoAC9NkyqaAFOPZTaK0P/8jvu8m+t9pWmDXPmqdRDgIgI7rI/g8j51RFtlM5CBpH\nmUkpxyqvChVI1A0DTVFLJd4=\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; @@ -535,11 +541,13 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test subject key ID does not match + // crl_signer_cert is not valid and just used for testing jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "BF42B7094DEBD515EC6ECF33B81115225F325289", "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIBvTCCAWSgAwIBAgIITqjoMYLUHBwwCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowMDEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABLbLY3KIfyko9brIGqnZOuJDHK2p154kL2UXfvnO2TKijs0Duq9qj8oYShpQ\nNUKWDUU/MD8fGUIddR6Pjxqam3WjZjBkMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD\nVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAfBgNV\nHSMEGDAWgBRq/SJ3H1Ef7L8WQZdnENzcMaFxfjAKBggqhkjOPQQDAgNHADBEAiBQ\nqoAC9NkyqaAFOPZTaK0P/8jvu8m+t9pWmDXPmqdRDgIgI7rI/g8j51RFtlM5CBpH\nmUkpxyqvChVI1A0DTVFLJd4=\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["0C694F7F866067B2"] }] )"; @@ -548,11 +556,13 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); // Test serial number does not match + // crl_signer_cert is not valid and just used for testing jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["3E6CE6509AD840CD1", "BC694F7F866067B1"] }] )"; @@ -560,16 +570,64 @@ TEST_F(TestDeviceAttestationCredentials, TestDACRevocationDelegateImpl) revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); - // Test starting serial number bytes match but not all + // Test starting serial number bytes match but not all, + // crl_signer_cert is not valid and just used for testing jsonData = R"( [{ "type": "revocation_set", "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", "revoked_serial_numbers": ["0C694F7F866067B21234"] }] )"; WriteTestRevokedData(jsonData, tmpJsonFile); revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); + + // Test DAC is revoked, and crl signer delegator is present + // crl_signer_cert is not valid and just used for testing + jsonData = R"( + [{ + "type": "revocation_set", + "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", + "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", + "crl_signer_delegator": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", + "revoked_serial_numbers": ["0C694F7F866067B2"] + }] + )"; + WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + EXPECT_EQ(attestationResult, AttestationVerificationResult::kDacRevoked); + + // Test with invalid crl signer cert missing begin and end cert markers + jsonData = R"( + [{ + "type": "revocation_set", + "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", + "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "MIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nTWF0dGVyIFRlc3QgUEFBMRQwEgYKKwYBBAGConwCAQwERkZGMTAgFw0yMTA2Mjgx\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==" + "revoked_serial_numbers": ["0C694F7F866067B2"] + }] + )"; + + WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); + + // test with malformed crl signer certificate + jsonData = R"( + [{ + "type": "revocation_set", + "issuer_subject_key_id": "AF42B7094DEBD515EC6ECF33B81115225F325288", + "issuer_name": "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw", + "crl_signer_cert": "-----BEGIN CERTIFICATE-----\nMIIB1DCCAXqgAwIBAgIIPmzmUJrYQM0wCgYIKoZIzj0EAwIwMDEYMBYGA1UEAwwP\nNDIzNDNaGA85OTk5MTIzMTIzNTk1OVowRjEYMBYGA1UEAwwPTWF0dGVyIFRlc3Qg\nUEFJMRQwEgYKKwYBBAGConwCAQwERkZGMTEUMBIGCisGAQQBgqJ8AgIMBDgwMDAw\nWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASA3fEbIo8+MfY7z1eY2hRiOuu96C7z\neO6tv7GP4avOMdCO1LIGBLbMxtm1+rZOfeEMt0vgF8nsFRYFbXDyzQsio2YwZDAS\nBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUr0K3\nCU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh\ncX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET\ni+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ==\n-----END CERTIFICATE-----", + "revoked_serial_numbers": ["0C694F7F866067B2"] + }] + )"; + + WriteTestRevokedData(jsonData, tmpJsonFile); + revocationDelegateImpl.CheckForRevokedDACChain(info, &attestationInformationVerificationCallback); + EXPECT_EQ(attestationResult, AttestationVerificationResult::kSuccess); } From 1ad661e349ee74a6d2073a2a4d994bc147ae7467 Mon Sep 17 00:00:00 2001 From: sarthak shaha Date: Wed, 27 Nov 2024 07:38:24 -0500 Subject: [PATCH 098/219] removed unnecessary include (#36646) --- examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp index 43c5a5573b..e693a26021 100644 --- a/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp +++ b/examples/platform/silabs/sensors/AirQuality/AirQualitySensor.cpp @@ -26,7 +26,6 @@ extern "C" { #endif #include -#include } #include "sl_i2cspm_instances.h" #endif // USE_SPARKFUN_AIR_QUALITY_SENSOR From 29165e9ed958adf05395804ef50631365836ced3 Mon Sep 17 00:00:00 2001 From: shgutte <102281713+shgutte@users.noreply.github.com> Date: Wed, 27 Nov 2024 19:27:19 +0530 Subject: [PATCH 099/219] [Silabs] Adds fix for support default value in refrigerator alarm cluster Refrigerator application (#36651) * Adds changes for supported value * Adds changes for the supported value --- .../silabs/data_model/refrigerator-thread-app.matter | 2 +- .../silabs/data_model/refrigerator-thread-app.zap | 2 +- .../silabs/data_model/refrigerator-wifi-app.matter | 2 +- .../silabs/data_model/refrigerator-wifi-app.zap | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter index 4cafac3925..813ade5379 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.matter @@ -1929,7 +1929,7 @@ endpoint 1 { server cluster RefrigeratorAlarm { ram attribute mask default = 1; ram attribute state default = 0; - ram attribute supported default = 0; + ram attribute supported default = 1; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap index 31351d35ef..d5933140ef 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-thread-app.zap @@ -3453,7 +3453,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter index 234974cf1d..857c8058f1 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.matter @@ -1837,7 +1837,7 @@ endpoint 1 { server cluster RefrigeratorAlarm { ram attribute mask default = 1; ram attribute state default = 0; - ram attribute supported default = 0; + ram attribute supported default = 1; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; diff --git a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap index 34ba99ff80..53f028aef1 100644 --- a/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap +++ b/examples/refrigerator-app/silabs/data_model/refrigerator-wifi-app.zap @@ -3358,7 +3358,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, From e98f2b239aae657a10043bad9aa61f4717d059be Mon Sep 17 00:00:00 2001 From: Ricardo Casallas <77841255+rcasallas-silabs@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:53:03 -0500 Subject: [PATCH 100/219] [Silabs] PSA Crypto PAL customized for EFR32. (#36575) * [Silabs] PSA Crypto PAL customized for EFR32. --- src/crypto/BUILD.gn | 24 +- src/crypto/DefaultSessionKeystore.h | 8 +- src/crypto/crypto.gni | 4 + src/crypto/tests/TestChipCryptoPAL.cpp | 9 +- .../silabs/efr32/CHIPCryptoPALPsaEfr32.cpp | 339 +++++++++++------- src/platform/silabs/efr32/args.gni | 1 + 6 files changed, 247 insertions(+), 138 deletions(-) diff --git a/src/crypto/BUILD.gn b/src/crypto/BUILD.gn index 6f82c93c19..235e8e2f43 100644 --- a/src/crypto/BUILD.gn +++ b/src/crypto/BUILD.gn @@ -38,6 +38,18 @@ assert( chip_crypto == "platform", "Please select a valid crypto implementation: mbedtls, psa, openssl, boringssl, platform") +if (chip_crypto_keystore == "") { + if (chip_crypto == "psa") { + chip_crypto_keystore = "psa" + } else { + chip_crypto_keystore = "raw" + } +} + +assert(chip_crypto_keystore == "psa" || chip_crypto_keystore == "raw" || + chip_crypto_keystore == "app", + "Please select a valid crypto keystore: psa, raw, app") + buildconfig_header("crypto_buildconfig") { header = "CryptoBuildConfig.h" header_dir = "crypto" @@ -47,11 +59,17 @@ buildconfig_header("crypto_buildconfig") { chip_crypto_openssl = chip_crypto == "openssl" chip_crypto_boringssl = chip_crypto == "boringssl" chip_crypto_platform = chip_crypto == "platform" + chip_crypto_keystore_psa = chip_crypto_keystore == "psa" + chip_crypto_keystore_raw = chip_crypto_keystore == "raw" + chip_crypto_keystore_app = chip_crypto_keystore == "app" defines = [ "CHIP_CRYPTO_MBEDTLS=${chip_crypto_mbedtls}", "CHIP_CRYPTO_PSA=${chip_crypto_psa}", "CHIP_CRYPTO_PSA_SPAKE2P=${chip_crypto_psa_spake2p}", + "CHIP_CRYPTO_KEYSTORE_PSA=${chip_crypto_keystore_psa}", + "CHIP_CRYPTO_KEYSTORE_RAW=${chip_crypto_keystore_raw}", + "CHIP_CRYPTO_KEYSTORE_APP=${chip_crypto_keystore_app}", "CHIP_CRYPTO_OPENSSL=${chip_crypto_openssl}", "CHIP_CRYPTO_BORINGSSL=${chip_crypto_boringssl}", "CHIP_CRYPTO_PLATFORM=${chip_crypto_platform}", @@ -144,18 +162,20 @@ static_library("crypto") { "RandUtils.h", ] - if (chip_crypto == "psa") { + if (chip_crypto_keystore == "psa") { sources += [ "PSAOperationalKeystore.cpp", "PSAOperationalKeystore.h", "PSASessionKeystore.cpp", "PSASessionKeystore.h", ] - } else { + } else if (chip_crypto_keystore == "raw") { sources += [ "RawKeySessionKeystore.cpp", "RawKeySessionKeystore.h", ] + } else { + # Keystore provided by app } if (chip_crypto_psa_spake2p) { diff --git a/src/crypto/DefaultSessionKeystore.h b/src/crypto/DefaultSessionKeystore.h index 8fa6121af5..227455b113 100644 --- a/src/crypto/DefaultSessionKeystore.h +++ b/src/crypto/DefaultSessionKeystore.h @@ -21,9 +21,9 @@ #include #endif -#if CHIP_CRYPTO_PSA +#if CHIP_CRYPTO_KEYSTORE_PSA #include -#else +#elif CHIP_CRYPTO_KEYSTORE_RAW #include #endif @@ -34,9 +34,9 @@ namespace Crypto { // when the PSA crypto backend is used, AES encryption/decryption function assume that the input // key handle carries a key reference instead of raw key material, so PSASessionKeystore must be // used instead of RawKeySessionKeystore to initialize the key handle. -#if CHIP_CRYPTO_PSA +#if CHIP_CRYPTO_KEYSTORE_PSA using DefaultSessionKeystore = PSASessionKeystore; -#else +#elif CHIP_CRYPTO_KEYSTORE_RAW using DefaultSessionKeystore = RawKeySessionKeystore; #endif diff --git a/src/crypto/crypto.gni b/src/crypto/crypto.gni index 96f506033b..2630af95b2 100644 --- a/src/crypto/crypto.gni +++ b/src/crypto/crypto.gni @@ -22,6 +22,10 @@ declare_args() { # Use PSA Spake2+ implementation. Only used if chip_crypto == "psa" chip_crypto_psa_spake2p = false + + # Crypto storage: psa, raw, app. + # app: includes zero new files and disables the unit tests for the keystore. + chip_crypto_keystore = "" } assert( diff --git a/src/crypto/tests/TestChipCryptoPAL.cpp b/src/crypto/tests/TestChipCryptoPAL.cpp index 2d1f5c0612..4dd5182e78 100644 --- a/src/crypto/tests/TestChipCryptoPAL.cpp +++ b/src/crypto/tests/TestChipCryptoPAL.cpp @@ -210,6 +210,7 @@ const AesCtrTestEntry theAesCtrTestVector[] = { } }; +#if !(CHIP_CRYPTO_KEYSTORE_APP) struct TestAesKey { public: @@ -245,6 +246,7 @@ struct TestHmacKey DefaultSessionKeystore keystore; Hmac128KeyHandle key; }; +#endif static void TestAES_CTR_128_Encrypt(const AesCtrTestEntry * vector) { @@ -964,6 +966,7 @@ TEST_F(TestChipCryptoPAL, TestHMAC_SHA256_RawKey) EXPECT_EQ(numOfTestsExecuted, numOfTestCases); } +#if !(CHIP_CRYPTO_KEYSTORE_APP) TEST_F(TestChipCryptoPAL, TestHMAC_SHA256_KeyHandle) { HeapChecker heapChecker; @@ -994,6 +997,7 @@ TEST_F(TestChipCryptoPAL, TestHMAC_SHA256_KeyHandle) } EXPECT_EQ(numOfTestsExecuted, numOfTestCases); } +#endif TEST_F(TestChipCryptoPAL, TestHKDF_SHA256) { @@ -1870,7 +1874,6 @@ TEST_F(TestChipCryptoPAL, TestSPAKE2P_RFC) size_t Pverifier_len = sizeof(Pverifier); uint8_t Vverifier[kMAX_Hash_Length]; size_t Vverifier_len = sizeof(Vverifier); - DefaultSessionKeystore keystore; int numOfTestVectors = ArraySize(rfc_tvs); int numOfTestsRan = 0; @@ -1967,7 +1970,9 @@ TEST_F(TestChipCryptoPAL, TestSPAKE2P_RFC) error = Verifier.KeyConfirm(Pverifier, Pverifier_len); EXPECT_EQ(error, CHIP_NO_ERROR); +#if !(CHIP_CRYPTO_KEYSTORE_APP) // Import HKDF key from the test vector to the keystore + DefaultSessionKeystore keystore; HkdfKeyHandle vectorKe; error = keystore.CreateKey(ByteSpan(vector->Ke, vector->Ke_len), vectorKe); EXPECT_EQ(error, CHIP_NO_ERROR); @@ -1988,7 +1993,7 @@ TEST_F(TestChipCryptoPAL, TestSPAKE2P_RFC) keystore.DestroyKey(vectorKe); keystore.DestroyKey(PKe); keystore.DestroyKey(VKe); - +#endif numOfTestsRan += 1; } EXPECT_GT(numOfTestsRan, 0); diff --git a/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp b/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp index a1811a1093..fc926ab5a8 100644 --- a/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp +++ b/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp @@ -26,6 +26,7 @@ #define MBEDTLS_ALLOW_PRIVATE_ACCESS #include +#include #include @@ -98,7 +99,9 @@ using chip::Platform::MemoryFree; #define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x #endif -static void _log_mbedTLS_error(int error_code) +namespace { + +void _log_mbedTLS_error(int error_code) { if (error_code != 0) { @@ -113,7 +116,7 @@ static void _log_mbedTLS_error(int error_code) } } -static void _log_PSA_error(psa_status_t status) +void _log_PSA_error(psa_status_t status) { if (status != 0) { @@ -122,15 +125,6 @@ static void _log_PSA_error(psa_status_t status) } } -static bool _isValidTagLength(size_t tag_length) -{ - if (tag_length == 8 || tag_length == 12 || tag_length == 16) - { - return true; - } - return false; -} - /** * @brief Compare two times * @@ -138,7 +132,7 @@ static bool _isValidTagLength(size_t tag_length) * @param t2 Second time to compare * @return int 0 If both times are idential to the second, -1 if t1 < t2, 1 if t1 > t2. */ -static int timeCompare(mbedtls_x509_time * t1, mbedtls_x509_time * t2) +int TimeCompare(mbedtls_x509_time * t1, mbedtls_x509_time * t2) { VerifyOrReturnValue(t1->year >= t2->year, -1); VerifyOrReturnValue(t1->year <= t2->year, 1); @@ -161,121 +155,117 @@ static int timeCompare(mbedtls_x509_time * t1, mbedtls_x509_time * t2) return 0; } +bool IsBufferNonEmpty(const uint8_t * data, size_t data_length) +{ + return data != nullptr && data_length > 0; +} + +bool IsValidTag(const uint8_t * tag, size_t tag_length) +{ + return tag != nullptr && (tag_length == 8 || tag_length == 12 || tag_length == 16); +} + +} // namespace + CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length, const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext, uint8_t * tag, size_t tag_length) { - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - size_t output_length = 0; - uint8_t * buffer = nullptr; - bool allocated_buffer = false; + VerifyOrReturnError(IsBufferNonEmpty(nonce, nonce_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsValidTag(tag, tag_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((ciphertext != nullptr && plaintext != nullptr) || plaintext_length == 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(aad != nullptr || aad_length == 0, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(CanCastTo(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length); + psa_status_t status = PSA_SUCCESS; + psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + size_t out_length; + size_t tag_out_length; - // If the ciphertext and tag outputs aren't a contiguous buffer, the PSA API requires buffer copying - if (Uint8::to_uchar(ciphertext) + plaintext_length != Uint8::to_uchar(tag)) - { - buffer = (uint8_t *) MemoryCalloc(1, plaintext_length + tag_length); - allocated_buffer = true; - VerifyOrExit(buffer != nullptr, error = CHIP_ERROR_NO_MEMORY); - } - - psa_crypto_init(); + status = psa_aead_encrypt_setup(&operation, key.As(), algorithm); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - psa_set_key_type(&attr, PSA_KEY_TYPE_AES); - psa_set_key_bits(&attr, sizeof(Symmetric128BitsKeyByteArray) * 8); - psa_set_key_algorithm(&attr, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8)); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT); + status = psa_aead_set_lengths(&operation, aad_length, plaintext_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - status = psa_driver_wrapper_aead_encrypt(&attr, key.As(), sizeof(Symmetric128BitsKeyByteArray), - PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length), Uint8::to_const_uchar(nonce), - nonce_length, Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext), - plaintext_length, allocated_buffer ? buffer : ciphertext, - plaintext_length + tag_length, &output_length); + status = psa_aead_set_nonce(&operation, nonce, nonce_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == plaintext_length + tag_length, error = CHIP_ERROR_INTERNAL); + status = psa_aead_update_ad(&operation, aad, aad_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - if (allocated_buffer) + if (plaintext_length != 0) { - memcpy(Uint8::to_uchar(ciphertext), buffer, plaintext_length); - memcpy(Uint8::to_uchar(tag), buffer + plaintext_length, tag_length); - memset(buffer, 0, plaintext_length + tag_length); - } + status = psa_aead_update(&operation, plaintext, plaintext_length, ciphertext, + PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, plaintext_length), &out_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); -exit: - if (allocated_buffer) + ciphertext += out_length; + + status = psa_aead_finish(&operation, ciphertext, PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &out_length, tag, + tag_length, &tag_out_length); + } + else { - MemoryFree(buffer); + status = psa_aead_finish(&operation, nullptr, 0, &out_length, tag, tag_length, &tag_out_length); } - psa_reset_key_attributes(&attr); - return error; + VerifyOrReturnError(status == PSA_SUCCESS && tag_length == tag_out_length, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; } -CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len, +CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length, const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * plaintext) { - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - size_t output_length = 0; - uint8_t * buffer = nullptr; - bool allocated_buffer = false; + VerifyOrReturnError(IsBufferNonEmpty(nonce, nonce_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsValidTag(tag, tag_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError((ciphertext != nullptr && plaintext != nullptr) || ciphertext_length == 0, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(aad != nullptr || aad_length == 0, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); + const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length); + psa_status_t status = PSA_SUCCESS; + psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + size_t outLength; - // If the ciphertext and tag outputs aren't a contiguous buffer, the PSA API requires buffer copying - if (Uint8::to_const_uchar(ciphertext) + ciphertext_len != Uint8::to_const_uchar(tag)) - { - buffer = (uint8_t *) MemoryCalloc(1, ciphertext_len + tag_length); - allocated_buffer = true; - VerifyOrExit(buffer != nullptr, error = CHIP_ERROR_NO_MEMORY); - } + status = psa_aead_decrypt_setup(&operation, key.As(), algorithm); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - psa_crypto_init(); + status = psa_aead_set_lengths(&operation, aad_length, ciphertext_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - psa_set_key_type(&attr, PSA_KEY_TYPE_AES); - psa_set_key_bits(&attr, sizeof(Symmetric128BitsKeyByteArray) * 8); - psa_set_key_algorithm(&attr, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8)); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DECRYPT); + status = psa_aead_set_nonce(&operation, nonce, nonce_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - if (allocated_buffer) + if (aad_length != 0) { - memcpy(buffer, ciphertext, ciphertext_len); - memcpy(buffer + ciphertext_len, tag, tag_length); + status = psa_aead_update_ad(&operation, aad, aad_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); } - - status = - psa_driver_wrapper_aead_decrypt(&attr, key.As(), sizeof(Symmetric128BitsKeyByteArray), - PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length), Uint8::to_const_uchar(nonce), - nonce_length, Uint8::to_const_uchar(aad), aad_len, allocated_buffer ? buffer : ciphertext, - ciphertext_len + tag_length, plaintext, ciphertext_len, &output_length); - - if (allocated_buffer) + else { - memset(buffer, 0, ciphertext_len + tag_length); + ChipLogDetail(Crypto, "AES_CCM_decrypt: Using aad == null path"); } - VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == ciphertext_len, error = CHIP_ERROR_INTERNAL); -exit: - if (allocated_buffer) + if (ciphertext_length != 0) + { + status = psa_aead_update(&operation, ciphertext, ciphertext_length, plaintext, + PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm, ciphertext_length), &outLength); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + plaintext += outLength; + + status = psa_aead_verify(&operation, plaintext, PSA_AEAD_VERIFY_OUTPUT_SIZE(PSA_KEY_TYPE_AES, algorithm), &outLength, tag, + tag_length); + } + else { - MemoryFree(buffer); + status = psa_aead_verify(&operation, nullptr, 0, &outLength, tag, tag_length); } - psa_reset_key_attributes(&attr); - return error; + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; } CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer) @@ -832,46 +822,45 @@ bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n) CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target) { - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair); - size_t output_length; + VerifyOrReturnError(!mInitialized, CHIP_ERROR_INCORRECT_STATE); - if (mInitialized) - { - return CHIP_ERROR_INCORRECT_STATE; - } + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + PsaP256KeypairContext & context = ToPsaContext(mKeypair); + size_t publicKeyLength = 0; - // Step 1: Generate a volatile new key - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - psa_crypto_init(); - - psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); - psa_set_key_bits(&attr, 256); - psa_set_key_algorithm(&attr, PSA_ALG_ECDH); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); + // Type based on ECC with the elliptic curve SECP256r1 -> PSA_ECC_FAMILY_SECP_R1 + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&attributes, kP256_PrivateKey_Length * 8); - status = psa_driver_wrapper_generate_key(&attr, keypair->privkey, sizeof(keypair->privkey), &output_length); + if (key_target == ECPKeyTarget::ECDH) + { + psa_set_key_algorithm(&attributes, PSA_ALG_ECDH); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); + } + else if (key_target == ECPKeyTarget::ECDSA) + { + psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE); + } + else + { + ExitNow(error = CHIP_ERROR_UNKNOWN_KEY_TYPE); + } + status = psa_generate_key(&attributes, &context.key_id); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == kP256_PrivateKey_Length, error = CHIP_ERROR_INTERNAL); - - keypair->bitlen = 256; - - // Step 2: Export the public key into the pubkey member - status = psa_driver_wrapper_export_public_key(&attr, keypair->privkey, sizeof(keypair->privkey), Uint8::to_uchar(mPublicKey), - mPublicKey.Length(), &output_length); + status = psa_export_public_key(context.key_id, mPublicKey.Bytes(), mPublicKey.Length(), &publicKeyLength); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == kP256_PublicKey_Length, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(publicKeyLength == kP256_PublicKey_Length, error = CHIP_ERROR_INTERNAL); + + mInitialized = true; exit: - _log_PSA_error(status); - if (error == CHIP_NO_ERROR) - { - mInitialized = true; - } - psa_reset_key_attributes(&attr); + LogPsaError(status); + psa_reset_key_attributes(&attributes); return error; } @@ -1690,15 +1679,15 @@ CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t root VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kRootFormatInvalid, error = CHIP_ERROR_INTERNAL)); /* Validates that intermediate and root certificates are valid at the time of the leaf certificate's start time. */ - compare_from = timeCompare(&leaf_valid_from, &rootCert.valid_from); - compare_until = timeCompare(&leaf_valid_from, &rootCert.valid_to); + compare_from = TimeCompare(&leaf_valid_from, &rootCert.valid_from); + compare_until = TimeCompare(&leaf_valid_from, &rootCert.valid_to); VerifyOrExit((compare_from >= 0) && (compare_until <= 0), (result = CertificateChainValidationResult::kChainInvalid, error = CHIP_ERROR_CERT_NOT_TRUSTED)); cert = certChain.next; while (cert) { - compare_from = timeCompare(&leaf_valid_from, &cert->valid_from); - compare_until = timeCompare(&leaf_valid_from, &cert->valid_to); + compare_from = TimeCompare(&leaf_valid_from, &cert->valid_from); + compare_until = TimeCompare(&leaf_valid_from, &cert->valid_to); VerifyOrExit((compare_from >= 0) && (compare_until <= 0), (result = CertificateChainValidationResult::kChainInvalid, error = CHIP_ERROR_CERT_NOT_TRUSTED)); cert = cert->next; @@ -2419,5 +2408,95 @@ CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, #endif // defined(MBEDTLS_X509_CRT_PARSE_C) } +void LogPsaError(psa_status_t status) +{ + if (status != PSA_SUCCESS) + { + ChipLogError(Crypto, "PSA error: %d", static_cast(status)); + } +} + +CHIP_ERROR PsaKdf::Init(const ByteSpan & secret, const ByteSpan & salt, const ByteSpan & info) +{ + psa_status_t status = PSA_SUCCESS; + psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_type(&attrs, PSA_KEY_TYPE_DERIVE); + psa_set_key_algorithm(&attrs, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_DERIVE); + + status = psa_import_key(&attrs, secret.data(), secret.size(), &mSecretKeyId); + LogPsaError(status); + psa_reset_key_attributes(&attrs); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + return InitOperation(mSecretKeyId, salt, info); +} + +CHIP_ERROR PsaKdf::Init(const HkdfKeyHandle & hkdfKey, const ByteSpan & salt, const ByteSpan & info) +{ + return InitOperation(hkdfKey.As(), salt, info); +} + +CHIP_ERROR PsaKdf::InitOperation(psa_key_id_t hkdfKey, const ByteSpan & salt, const ByteSpan & info) +{ + psa_status_t status = psa_key_derivation_setup(&mOperation, PSA_ALG_HKDF(PSA_ALG_SHA_256)); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + if (salt.size() > 0) + { + status = psa_key_derivation_input_bytes(&mOperation, PSA_KEY_DERIVATION_INPUT_SALT, salt.data(), salt.size()); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + } + + status = psa_key_derivation_input_key(&mOperation, PSA_KEY_DERIVATION_INPUT_SECRET, hkdfKey); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + status = psa_key_derivation_input_bytes(&mOperation, PSA_KEY_DERIVATION_INPUT_INFO, info.data(), info.size()); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PsaKdf::DeriveBytes(const MutableByteSpan & output) +{ + psa_status_t status = psa_key_derivation_output_bytes(&mOperation, output.data(), output.size()); + LogPsaError(status); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PsaKdf::DeriveKey(const psa_key_attributes_t & attributes, psa_key_id_t & keyId) +{ + psa_status_t status = psa_key_derivation_output_key(&attributes, &mOperation, &keyId); + LogPsaError(status); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FindFreeKeySlotInRange(psa_key_id_t & keyId, psa_key_id_t start, uint32_t range) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t end = start + range; + + VerifyOrReturnError(start >= PSA_KEY_ID_USER_MIN && end - 1 <= PSA_KEY_ID_USER_MAX, CHIP_ERROR_INVALID_ARGUMENT); + + for (keyId = start; keyId < end; keyId++) + { + psa_status_t status = psa_get_key_attributes(keyId, &attributes); + if (status == PSA_ERROR_INVALID_HANDLE) + { + return CHIP_NO_ERROR; + } + else if (status != PSA_SUCCESS) + { + return CHIP_ERROR_INTERNAL; + } + } + return CHIP_ERROR_NOT_FOUND; +} + } // namespace Crypto } // namespace chip diff --git a/src/platform/silabs/efr32/args.gni b/src/platform/silabs/efr32/args.gni index 501661866a..95b7519474 100644 --- a/src/platform/silabs/efr32/args.gni +++ b/src/platform/silabs/efr32/args.gni @@ -29,6 +29,7 @@ openthread_external_mbedtls = mbedtls_target # default to platform crypto implementation but allow commandline override if (chip_crypto == "") { chip_crypto = "platform" + chip_crypto_keystore = "psa" } chip_device_platform = "efr32" From cb1f4b0432baf96de7a4cdef4965cd1e08c720c4 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:59:59 -0500 Subject: [PATCH 101/219] Adds SubscriptionInfoProvider API to check if a given fabric has at least 1 subscription (#36627) * [SL-UP] Add fabric subscription check to the interaction model engine (#117) * Remove unwanted change * Restyle * Improve readability * Restyled by clang-format * Update src/app/SubscriptionsInfoProvider.h Co-authored-by: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> --------- Co-authored-by: Restyled.io Co-authored-by: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> --- src/app/InteractionModelEngine.cpp | 22 ++++ src/app/InteractionModelEngine.h | 2 + src/app/SubscriptionsInfoProvider.h | 10 ++ src/app/icd/server/tests/TestICDManager.cpp | 1 + src/app/tests/TestInteractionModelEngine.cpp | 121 +++++++++++++++++++ 5 files changed, 156 insertions(+) diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 9b76dd31bf..56acd09661 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -462,6 +462,28 @@ bool InteractionModelEngine::SubjectHasPersistedSubscription(FabricIndex aFabric return persistedSubMatches; } +bool InteractionModelEngine::FabricHasAtLeastOneActiveSubscription(FabricIndex aFabricIndex) +{ + bool hasActiveSubscription = false; + mReadHandlers.ForEachActiveObject([aFabricIndex, &hasActiveSubscription](ReadHandler * handler) { + VerifyOrReturnValue(handler->IsType(ReadHandler::InteractionType::Subscribe), Loop::Continue); + + Access::SubjectDescriptor subject = handler->GetSubjectDescriptor(); + VerifyOrReturnValue(subject.fabricIndex == aFabricIndex, Loop::Continue); + + if ((subject.authMode == Access::AuthMode::kCase) && handler->IsActiveSubscription()) + { + // On first subscription found for fabric, we can immediately stop checking. + hasActiveSubscription = true; + return Loop::Break; + } + + return Loop::Continue; + }); + + return hasActiveSubscription; +} + void InteractionModelEngine::OnDone(CommandResponseSender & apResponderObj) { mCommandResponderObjs.ReleaseObject(&apResponderObj); diff --git a/src/app/InteractionModelEngine.h b/src/app/InteractionModelEngine.h index 3fa379129a..36aa2ccc6e 100644 --- a/src/app/InteractionModelEngine.h +++ b/src/app/InteractionModelEngine.h @@ -315,6 +315,8 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, bool SubjectHasPersistedSubscription(FabricIndex aFabricIndex, NodeId subjectID) override; + bool FabricHasAtLeastOneActiveSubscription(FabricIndex aFabricIndex) override; + #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS /** * @brief Function decrements the number of subscriptions to resume counter - mNumOfSubscriptionsToResume. diff --git a/src/app/SubscriptionsInfoProvider.h b/src/app/SubscriptionsInfoProvider.h index cb8d470cbb..6fe383e1ff 100644 --- a/src/app/SubscriptionsInfoProvider.h +++ b/src/app/SubscriptionsInfoProvider.h @@ -61,6 +61,16 @@ class SubscriptionsInfoProvider * false subject doesn't have any persisted subscription with the device */ virtual bool SubjectHasPersistedSubscription(FabricIndex aFabricIndex, NodeId subjectID) = 0; + + /** + * @brief Check if a given fabric has at least 1 active subscription. + * + * @param aFabricIndex fabric index for which we want to validate is has at least one active subscription + * + * @return true fabric has at least one active subscription + * false fabric doesn't have any active subscription or failed to validate + */ + virtual bool FabricHasAtLeastOneActiveSubscription(FabricIndex aFabricIndex) = 0; }; } // namespace app diff --git a/src/app/icd/server/tests/TestICDManager.cpp b/src/app/icd/server/tests/TestICDManager.cpp index f6f999c1a3..4d0791c714 100644 --- a/src/app/icd/server/tests/TestICDManager.cpp +++ b/src/app/icd/server/tests/TestICDManager.cpp @@ -122,6 +122,7 @@ class TestSubscriptionsInfoProvider : public SubscriptionsInfoProvider bool SubjectHasActiveSubscription(FabricIndex aFabricIndex, NodeId subject) { return mHasActiveSubscription; }; bool SubjectHasPersistedSubscription(FabricIndex aFabricIndex, NodeId subject) { return mHasPersistedSubscription; }; + bool FabricHasAtLeastOneActiveSubscription(FabricIndex aFabricIndex) { return false; }; private: bool mHasActiveSubscription = false; diff --git a/src/app/tests/TestInteractionModelEngine.cpp b/src/app/tests/TestInteractionModelEngine.cpp index acc19c12f4..88b3c07a6d 100644 --- a/src/app/tests/TestInteractionModelEngine.cpp +++ b/src/app/tests/TestInteractionModelEngine.cpp @@ -68,6 +68,8 @@ class TestInteractionModelEngine : public chip::Test::AppContext void TestSubjectHasActiveSubscriptionSubWithCAT(); void TestSubscriptionResumptionTimer(); void TestDecrementNumSubscriptionsToResume(); + void TestFabricHasAtLeastOneActiveSubscription(); + void TestFabricHasAtLeastOneActiveSubscriptionWithMixedStates(); static int GetAttributePathListLength(SingleLinkedListNode * apattributePathParamsList); }; @@ -720,5 +722,124 @@ TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestDecrementNumSubscriptionsToR } #endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS +TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestFabricHasAtLeastOneActiveSubscription) +{ + NullReadHandlerCallback nullCallback; + InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + + FabricIndex fabricIndex1 = 1; + FabricIndex fabricIndex2 = 2; + + // Create ExchangeContexts + Messaging::ExchangeContext * exchangeCtx1 = NewExchangeToBob(nullptr, false); + ASSERT_TRUE(exchangeCtx1); + + Messaging::ExchangeContext * exchangeCtx2 = NewExchangeToAlice(nullptr, false); + ASSERT_TRUE(exchangeCtx2); + + // InteractionModelEngine init + EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); + + // Verify that both fabrics have no active subscriptions + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex1)); + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex2)); + + // Create and setup readHandler 1 + ReadHandler * readHandler1 = + engine->GetReadHandlerPool().CreateObject(nullCallback, exchangeCtx1, ReadHandler::InteractionType::Subscribe, + reporting::GetDefaultReportScheduler(), CodegenDataModelProviderInstance()); + + // Verify that fabric 1 still doesn't have an active subscription + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex1)); + + // Set readHandler1 to active + readHandler1->SetStateFlag(ReadHandler::ReadHandlerFlags::ActiveSubscription, true); + + // Verify that fabric 1 has an active subscription + EXPECT_TRUE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex1)); + + // Verify that fabric 2 still doesn't have an active subscription + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex2)); + + // Create and setup readHandler 2 + ReadHandler * readHandler2 = + engine->GetReadHandlerPool().CreateObject(nullCallback, exchangeCtx2, ReadHandler::InteractionType::Subscribe, + reporting::GetDefaultReportScheduler(), CodegenDataModelProviderInstance()); + + // Set readHandler2 to active + readHandler2->SetStateFlag(ReadHandler::ReadHandlerFlags::ActiveSubscription, true); + + // Verify that fabric 2 has an active subscription + EXPECT_TRUE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex2)); + + // Clean up read handlers + engine->GetReadHandlerPool().ReleaseAll(); + + // Verify that both fabrics have no active subscriptions + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex1)); + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex2)); +} + +TEST_F_FROM_FIXTURE(TestInteractionModelEngine, TestFabricHasAtLeastOneActiveSubscriptionWithMixedStates) +{ + NullReadHandlerCallback nullCallback; + InteractionModelEngine * engine = InteractionModelEngine::GetInstance(); + + FabricIndex fabricIndex = 1; + + // Create ExchangeContexts + Messaging::ExchangeContext * exchangeCtx1 = NewExchangeToBob(nullptr, false); + ASSERT_TRUE(exchangeCtx1); + + Messaging::ExchangeContext * exchangeCtx2 = NewExchangeToBob(nullptr, false); + ASSERT_TRUE(exchangeCtx2); + + // InteractionModelEngine init + EXPECT_EQ(CHIP_NO_ERROR, engine->Init(&GetExchangeManager(), &GetFabricTable(), reporting::GetDefaultReportScheduler())); + + // Verify that the fabric has no active subscriptions + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); + + // Create and setup readHandler 1 + ReadHandler * readHandler1 = + engine->GetReadHandlerPool().CreateObject(nullCallback, exchangeCtx1, ReadHandler::InteractionType::Subscribe, + reporting::GetDefaultReportScheduler(), CodegenDataModelProviderInstance()); + + // Verify that the fabric still doesn't have an active subscription + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); + + // Set readHandler1 to active + readHandler1->SetStateFlag(ReadHandler::ReadHandlerFlags::ActiveSubscription, true); + + // Verify that the fabric has an active subscription + EXPECT_TRUE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); + + // Create and setup readHandler 2 + ReadHandler * readHandler2 = + engine->GetReadHandlerPool().CreateObject(nullCallback, exchangeCtx2, ReadHandler::InteractionType::Subscribe, + reporting::GetDefaultReportScheduler(), CodegenDataModelProviderInstance()); + + // Verify that the fabric still has an active subscription + EXPECT_TRUE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); + + // Set readHandler2 to inactive + readHandler2->SetStateFlag(ReadHandler::ReadHandlerFlags::ActiveSubscription, false); + + // Verify that the fabric still has an active subscription + EXPECT_TRUE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); + + // Set readHandler1 to inactive + readHandler1->SetStateFlag(ReadHandler::ReadHandlerFlags::ActiveSubscription, false); + + // Verify that the fabric doesn't have an active subscription + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); + + // Clean up read handlers + engine->GetReadHandlerPool().ReleaseAll(); + + // Verify that the fabric has no active subscriptions + EXPECT_FALSE(engine->FabricHasAtLeastOneActiveSubscription(fabricIndex)); +} + } // namespace app } // namespace chip From e18e289e799d679cbe0ff80fefb6cf5f49a253c9 Mon Sep 17 00:00:00 2001 From: shgutte <102281713+shgutte@users.noreply.github.com> Date: Thu, 28 Nov 2024 00:53:23 +0530 Subject: [PATCH 102/219] [Silabs] Adds refrigerator app matter shell support for change door state (#36548) * Added changes for the matter shell * Added support for the matter shell refrigerator door state * Added changes for the failure * Adds required comment changes * Added restyler changes * Adds changes according to comment --- .../silabs/src/EventHandlerLibShell.cpp | 4 +- examples/refrigerator-app/silabs/BUILD.gn | 4 + .../silabs/include/EventHandlerLibShell.h | 36 ++++ .../refrigerator-app/silabs/src/AppTask.cpp | 14 +- .../silabs/src/EventHandlerLibShell.cpp | 178 ++++++++++++++++++ 5 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 examples/refrigerator-app/silabs/include/EventHandlerLibShell.h create mode 100644 examples/refrigerator-app/silabs/src/EventHandlerLibShell.cpp diff --git a/examples/lock-app/silabs/src/EventHandlerLibShell.cpp b/examples/lock-app/silabs/src/EventHandlerLibShell.cpp index ef79290bd1..d9b9244fc6 100644 --- a/examples/lock-app/silabs/src/EventHandlerLibShell.cpp +++ b/examples/lock-app/silabs/src/EventHandlerLibShell.cpp @@ -99,7 +99,7 @@ CHIP_ERROR AlarmEventHandler(int argc, char ** argv) if (argc >= 2) { ChipLogError(Zcl, "Too many arguments provided to function %s, line %d", __func__, __LINE__); - return APP_ERROR_TOO_MANY_SHELL_ARGUMENTS; + return CHIP_ERROR_INVALID_ARGUMENT; } AlarmEventData * data = Platform::New(); @@ -131,7 +131,7 @@ CHIP_ERROR DoorStateEventHandler(int argc, char ** argv) if (argc >= 2) { ChipLogError(Zcl, "Too many arguments provided to function %s, line %d", __func__, __LINE__); - return APP_ERROR_TOO_MANY_SHELL_ARGUMENTS; + return CHIP_ERROR_INVALID_ARGUMENT; } DoorStateEventData * data = Platform::New(); diff --git a/examples/refrigerator-app/silabs/BUILD.gn b/examples/refrigerator-app/silabs/BUILD.gn index 200c909b1f..d902bb9e86 100644 --- a/examples/refrigerator-app/silabs/BUILD.gn +++ b/examples/refrigerator-app/silabs/BUILD.gn @@ -143,6 +143,10 @@ silabs_executable("refrigerator_app") { "src/refrigerator-and-temperature-controlled-cabinet-mode.cpp", ] + if (chip_build_libshell) { + sources += [ "src/EventHandlerLibShell.cpp" ] + } + if (use_temp_sensor) { sources += [ "${efr32_sdk_root}/hardware/driver/si70xx/src/sl_si70xx.c", diff --git a/examples/refrigerator-app/silabs/include/EventHandlerLibShell.h b/examples/refrigerator-app/silabs/include/EventHandlerLibShell.h new file mode 100644 index 0000000000..5997b24d5b --- /dev/null +++ b/examples/refrigerator-app/silabs/include/EventHandlerLibShell.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 2024 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. + */ +#pragma once + +#include +#include +#include + +class EventData +{ +public: + chip::EventId eventId; +}; + +class RefrigeratorAlarmEventData : public EventData +{ +public: + chip::app::Clusters::RefrigeratorAlarm::AlarmBitmap doorState; +}; + +CHIP_ERROR RegisterRefrigeratorEvents(); +void EventWorkerFunction(intptr_t context); diff --git a/examples/refrigerator-app/silabs/src/AppTask.cpp b/examples/refrigerator-app/silabs/src/AppTask.cpp index d2def279be..c9dc451b71 100644 --- a/examples/refrigerator-app/silabs/src/AppTask.cpp +++ b/examples/refrigerator-app/silabs/src/AppTask.cpp @@ -24,7 +24,6 @@ #include "AppTask.h" #include "AppConfig.h" #include "AppEvent.h" - #include "LEDWidget.h" #ifdef DISPLAY_ENABLED @@ -35,6 +34,10 @@ #endif // QR_CODE_ENABLED #endif // DISPLAY_ENABLED +#if defined(ENABLE_CHIP_SHELL) +#include "EventHandlerLibShell.h" +#endif // ENABLE_CHIP_SHELL + #include #include #include @@ -94,6 +97,15 @@ CHIP_ERROR AppTask::Init() appError(err); } +#if defined(ENABLE_CHIP_SHELL) + err = RegisterRefrigeratorEvents(); + if (err != CHIP_NO_ERROR) + { + SILABS_LOG("RegisterRefrigeratorEvents() failed"); + appError(err); + } +#endif // ENABLE_CHIP_SHELL + return err; } diff --git a/examples/refrigerator-app/silabs/src/EventHandlerLibShell.cpp b/examples/refrigerator-app/silabs/src/EventHandlerLibShell.cpp new file mode 100644 index 0000000000..212b2ac8d8 --- /dev/null +++ b/examples/refrigerator-app/silabs/src/EventHandlerLibShell.cpp @@ -0,0 +1,178 @@ +/* + * + * Copyright (c) 2024 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. + */ + +#include "EventHandlerLibShell.h" +#include "AppTask.h" +#include "lib/shell/Engine.h" +#include "lib/shell/commands/Help.h" + +#include "app/server/Server.h" +#include "platform/CHIPDeviceLayer.h" +#include + +constexpr uint8_t kRefEndpointId = 1; + +using namespace chip; +using namespace chip::app; +using namespace Clusters::RefrigeratorAlarm; +using namespace Clusters::TemperatureControl; +using Shell::Engine; +using Shell::shell_command_t; +using Shell::streamer_get; +using Shell::streamer_printf; + +Engine sShellRefrigeratorSubCommands; +Engine sShellRefrigeratorEventSubCommands; +Engine sShellRefrigeratorEventAlarmDoorSubCommands; + +/******************************************************** + * Refrigerator shell functions + *********************************************************/ + +CHIP_ERROR RefrigeratorHelpHandler(int argc, char ** argv) +{ + sShellRefrigeratorSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR RefrigeratorCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return RefrigeratorHelpHandler(argc, argv); + } + + return sShellRefrigeratorSubCommands.ExecCommand(argc, argv); +} + +/******************************************************** + * Event shell functions + *********************************************************/ + +CHIP_ERROR EventHelpHandler(int argc, char ** argv) +{ + sShellRefrigeratorEventSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EventRefrigeratorCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return EventHelpHandler(argc, argv); + } + + return sShellRefrigeratorEventSubCommands.ExecCommand(argc, argv); +} + +/******************************************************** + * Alarm shell functions + *********************************************************/ + +CHIP_ERROR AlarmHelpHandler(int argc, char ** argv) +{ + sShellRefrigeratorEventAlarmDoorSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR RefrigeratorDoorEventHandler(int argc, char ** argv) +{ + + if (argc == 0) + { + return AlarmHelpHandler(argc, argv); + } + if (argc >= 2) + { + ChipLogError(Shell, "Too many arguments"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Check if the argument is a valid integer + if (argv[0] == nullptr || !std::all_of(argv[0], argv[0] + strlen(argv[0]), ::isdigit)) + { + ChipLogError(Shell, "Invalid argument: Input must be a valid integer."); + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Convert the argument to an integer + int value = std::stoi(argv[0]); // Safe to use now, as we validated the input earlier + + RefrigeratorAlarmEventData * data = Platform::New(); + data->eventId = Events::Notify::Id; + data->doorState = static_cast(value); + + DeviceLayer::PlatformMgr().ScheduleWork(EventWorkerFunction, reinterpret_cast(data)); + + return CHIP_NO_ERROR; +} + +/** + * @brief configures Refrigerator matter shell + * + */ + +CHIP_ERROR RegisterRefrigeratorEvents() +{ + static const shell_command_t sRefrigeratorSubCommands[] = { + { &RefrigeratorHelpHandler, "help", "Usage: refrigeratoralarm " }, + { &EventRefrigeratorCommandHandler, "event", " Usage: refrigeratoralarm event " } + }; + + static const shell_command_t sRefrigeratorEventSubCommands[] = { + { &EventHelpHandler, "help", "Usage : refrigeratoralarm event " }, + { &RefrigeratorDoorEventHandler, "door-state-change", "Sends door state change event to Refrigerator app" } + }; + + static const shell_command_t sRefrigeratorEventAlarmDoorSubCommands[] = { + { &AlarmHelpHandler, "help", "Usage : Refrigerator event to change door state" } + }; + + static const shell_command_t sRefrigeratorCommand = { &RefrigeratorCommandHandler, "refrigeratoralarm", + "refrigerator alarm commands. Usage: refrigeratoralarm " }; + + sShellRefrigeratorEventAlarmDoorSubCommands.RegisterCommands(sRefrigeratorEventAlarmDoorSubCommands, + ArraySize(sRefrigeratorEventAlarmDoorSubCommands)); + sShellRefrigeratorEventSubCommands.RegisterCommands(sRefrigeratorEventSubCommands, ArraySize(sRefrigeratorEventSubCommands)); + sShellRefrigeratorSubCommands.RegisterCommands(sRefrigeratorSubCommands, ArraySize(sRefrigeratorSubCommands)); + + Engine::Root().RegisterCommands(&sRefrigeratorCommand, 1); + + return CHIP_NO_ERROR; +} + +void EventWorkerFunction(intptr_t context) +{ + VerifyOrReturn(reinterpret_cast(context) != nullptr, ChipLogError(Shell, "EventWorkerFunction - Invalid work data")); + EventData * data = reinterpret_cast(context); + + switch (data->eventId) + { + case Events::Notify::Id: { + RefrigeratorAlarmEventData * alarmData = reinterpret_cast(context); + RefrigeratorAlarmServer::Instance().SetStateValue(kRefEndpointId, alarmData->doorState); + break; + } + + default: { + ChipLogError(Zcl, "Invalid Event Id %s, line %d", __func__, __LINE__); + break; + } + } + // Free memory + Platform::Delete(data); +} From 63bc8a34ddb37a6632b44868a17155d85671cde6 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Wed, 27 Nov 2024 11:43:43 -0800 Subject: [PATCH 103/219] [Fabric-Sync] Fix segment fault during fabric device sync (#36656) --- examples/fabric-sync/admin/FabricAdmin.cpp | 8 ++++++-- examples/fabric-sync/main.cpp | 22 +++------------------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/examples/fabric-sync/admin/FabricAdmin.cpp b/examples/fabric-sync/admin/FabricAdmin.cpp index 3e96af42af..1716692691 100644 --- a/examples/fabric-sync/admin/FabricAdmin.cpp +++ b/examples/fabric-sync/admin/FabricAdmin.cpp @@ -44,8 +44,12 @@ CHIP_ERROR FabricAdmin::Init() auto engine = chip::app::InteractionModelEngine::GetInstance(); VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnLogErrorOnFailure(IcdManager::Instance().Init(&sICDClientStorage, engine)); - ReturnLogErrorOnFailure(sCheckInHandler.Init(Controller::DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(), - &sICDClientStorage, &IcdManager::Instance(), engine)); + + auto exchangeMgr = Controller::DeviceControllerFactory::GetInstance().GetSystemState()->ExchangeMgr(); + VerifyOrReturnError(exchangeMgr != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnLogErrorOnFailure(sCheckInHandler.Init(exchangeMgr, &sICDClientStorage, &IcdManager::Instance(), engine)); + + ReturnLogErrorOnFailure(PairingManager::Instance().Init(GetDeviceCommissioner())); return CHIP_NO_ERROR; } diff --git a/examples/fabric-sync/main.cpp b/examples/fabric-sync/main.cpp index 1cad0d4965..7eed75cce9 100644 --- a/examples/fabric-sync/main.cpp +++ b/examples/fabric-sync/main.cpp @@ -87,6 +87,9 @@ void ApplicationInit() CHIP_ERROR err = bridge::BridgeInit(&admin::FabricAdmin::Instance()); VerifyOrDieWithMsg(err == CHIP_NO_ERROR, NotSpecified, "Fabric-Sync: Failed to initialize bridge, error: %s", ErrorStr(err)); + + err = admin::FabricAdmin::Instance().Init(); + VerifyOrDieWithMsg(err == CHIP_NO_ERROR, NotSpecified, "Fabric-Sync: Failed to initialize admin, error: %s", ErrorStr(err)); } void ApplicationShutdown() @@ -112,24 +115,5 @@ int main(int argc, char * argv[]) ChipLinuxAppMainLoop(); - CHIP_ERROR err = admin::FabricAdmin::Instance().Init(); - - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(NotSpecified, "Failed to init FabricAdmin: %s ", ErrorStr(err)); - - // End the program with non zero error code to indicate a error. - return 1; - } - - err = admin::PairingManager::Instance().Init(GetDeviceCommissioner()); - if (err != CHIP_NO_ERROR) - { - ChipLogProgress(NotSpecified, "Failed to init PairingManager: %s ", ErrorStr(err)); - - // End the program with non zero error code to indicate a error. - return 1; - } - return 0; } From 481270d86a048ad6b631fb55e5bd10acff104a26 Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Wed, 27 Nov 2024 15:04:18 -0500 Subject: [PATCH 104/219] energy-management-app: refactor WH and EVSE into separate endpoints and fix conformance issues (#36201) * Add missing Water Heater device to matter-devices.xml This PR adds the missing Water Heater device to matter-devices.xml. The description was generated using the Alchemy tool (https://github.com/project-chip/alchemy) with the following command: `alchemy zap --attribute="in-progress" --sdkRoot=./connectedhomeip/ --specRoot=./connectedhomeip-spec/ ./connectedhomeip-spec/src/device_types/WaterHeater.adoc` I manually fixed the device nae from `Matter Water Heater` to `Water Heater`. * zap regen * energy-management-app: Split WH and EVSE into 2 endpoints This PR refactors the energy-management-app into 2 separate endpoints (one for EVSE and another for WaterHeater). This is the first step in making this app spec-conformant. `TC_DeviceBasicComposition.py` failed on this app before this PR and now passes. Changes: * Split Water Heater and EVSE into two separate endpoints (1 and 2). Updated zap and code. * Dinamically disable unused endpoint at runtime. Based on the app choice (command line argument on linux or #define in ESP32 or SIlabs), initialize the clusters in the correct endpoint and disable the other endpoint. For example, for Water Heater, initialize clusters on endpoint 2 and disable endpoint 1 (EVSE). * Refactor/move the init code related to ElectricalSensor (PowerTopology, EPM and EEM) from inside EVSE into ElectricalSensorInit.h/.cpp so they can be easier to reuse by both WaterHeater and EVSE. * Refactor/move DEM cluster init code into its own file so it can be better reused outside EVSE. Test performed: 1. Check basic composition for EVSE: ``` scripts/run_in_python_env.sh out/python_env './scripts/tests/run_python_test.py --app ./out/linux-x64-energy-management-no-ble/chip-energy-management-app --app-args "--application evse --trace-to json:log" --script src/python_testing/TC_DeviceBasicComposition.py --script-args "--qr-code MT:-24J0AFN00KA0648G00"' ``` 2. Check basic composition for WaterHeater: ``` scripts/run_in_python_env.sh out/python_env './scripts/tests/run_python_test.py --app ./out/linux-x64-energy-management-no-ble/chip-energy-management-app --app-args "--application water-heater --trace-to json:log" --script src/python_testing/TC_DeviceBasicComposition.py --script-args "--qr-code MT:-24J0AFN00KA0648G00"' ``` 3. Check app against `TC_EEVSE_2_6.py`: ``` rm -f evse.bin; ./out/linux-x64-energy-management-no-ble/chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f --KVS evse.bin --featureSet 0x3d python src/python_testing/TC_EEVSE_2_6.py --endpoint 1 -m on-network -n 1234 -p 20202021 -d 3840 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f ``` * Use anon namespace instead of static. * disable enpoint on esp32 and silabs * address Tennessee's PR feedback * Review suggestion: move GetMainAppEndpointId to another file * zap regen * fix matter-devices white space diffs * App now builds on all-clusters app * Fix typo on init * fix all-clusters breakage on esp32 * fix misuse of namespace in header * Fix breakage for silabs water heater * Update WaterHeater endpoint for CI tests This fixes REPL test CI breakage. * Update WaterHeater tests to endpoint 2 * Bumped ClusterRevisions Cluster 40 (0x28) BasicInformation - 3 -> 4 Cluster 47 (0x2f) PowerSource - 2 -> 3 Cluster 48 (0x30) GeneralCommissioning 1-> 2 Cluster 3 (0x03) Identify 4 -> 5 Cluster 153 (0x99) EnergyEvse 2 -> 3 Cluster 157 (0x9d) EnergyEvseMode 1-> 2 Cluster 159 (0x9f) DeviceEnergyManagementMode 1-> 2 * Update AccessControl featureMap to enable Extension attribute * Remove AccessControl extension attribute * Remove kStateForecastReporting from the default feature map That feature can't be enabled together with kPowerAdjustment. * Update TC_WHM_1_2 endpoint to 2 * Fix various conformance issues Remove PowerSource from root node and move to EP1/evse Bump cluster revisions where needed Fix device type descriptions for each EP Remove unused Thermostat cluster and added a TODO. We need to properly implement this cluster for this app for temperature control. * TC_WHM_1_2: Use endpoint id passed as argument instead of hardcoded --- .../src/energy-evse-stub.cpp | 5 + .../all-clusters-app/linux/main-common.cpp | 3 +- .../include/EnergyManagementAppCommonMain.h} | 16 + .../src/EnergyManagementAppCommonMain.cpp | 410 +++ .../src/DEMTestEventTriggers.cpp | 22 +- .../src/device-energy-management-mode.cpp | 23 +- .../include/EVSEManufacturerImpl.h | 4 +- .../energy-evse/include/EnergyEvseMain.h | 22 +- .../energy-evse/src/EVSEManufacturerImpl.cpp | 23 +- .../energy-evse/src/EnergyEvseMain.cpp | 359 +- .../energy-management-app.matter | 187 +- .../energy-management-app.zap | 3102 +++++++++++------ .../include/ElectricalSensorInit.h} | 21 +- .../energy-reporting/src/FakeReadings.cpp | 2 +- .../water-heater/include/WhmMain.h | 2 +- .../water-heater/src/WaterHeaterMain.cpp | 101 - .../water-heater/src/WhmDelegateImpl.cpp | 1 + .../water-heater/src/WhmMain.cpp | 12 +- .../water-heater/src/water-heater-mode.cpp | 10 +- .../energy-management-app/esp32/main/main.cpp | 34 +- examples/energy-management-app/linux/BUILD.gn | 2 +- examples/energy-management-app/linux/main.cpp | 38 +- .../energy-management-app/silabs/BUILD.gn | 2 +- .../silabs/src/AppTask.cpp | 32 +- src/python_testing/TC_EWATERHTR_2_1.py | 2 +- src/python_testing/TC_EWATERHTR_2_2.py | 2 +- src/python_testing/TC_EWATERHTR_2_3.py | 2 +- src/python_testing/TC_WHM_1_2.py | 2 +- src/python_testing/TC_WHM_2_1.py | 2 +- 29 files changed, 2802 insertions(+), 1641 deletions(-) rename examples/energy-management-app/energy-management-common/{device-energy-management/include/DEMDelegate.h => common/include/EnergyManagementAppCommonMain.h} (54%) create mode 100644 examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp rename examples/energy-management-app/energy-management-common/{water-heater/include/WaterHeaterMain.h => energy-reporting/include/ElectricalSensorInit.h} (55%) delete mode 100644 examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp diff --git a/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp index 6acc81ac28..efaa19600b 100644 --- a/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp @@ -26,6 +26,11 @@ static std::unique_ptr gDelegate; static std::unique_ptr gEvseTargetsDelegate; static std::unique_ptr gInstance; +EndpointId GetEnergyDeviceEndpointId() +{ + return chip::EndpointId(1); +} + void emberAfEnergyEvseClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index b62d154f0d..22170885db 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -124,6 +124,7 @@ const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp3TagList[] = { { .tag = kTagSwitchesUp } }; const Clusters::Descriptor::Structs::SemanticTagStruct::Type gEp4TagList[] = { { .namespaceID = kNamespaceSwitches, .tag = kTagSwitchesDown } }; + } // namespace #ifdef MATTER_DM_PLUGIN_DISHWASHER_ALARM_SERVER @@ -256,7 +257,7 @@ void ApplicationInit() Clusters::ValveConfigurationAndControl::SetDefaultDelegate(chip::EndpointId(1), &sValveDelegate); Clusters::TimeSynchronization::SetDefaultDelegate(&sTimeSyncDelegate); - Clusters::WaterHeaterManagement::WhmApplicationInit(); + Clusters::WaterHeaterManagement::WhmApplicationInit(chip::EndpointId(1)); SetTagList(/* endpoint= */ 0, Span(gEp0TagList)); SetTagList(/* endpoint= */ 1, Span(gEp1TagList)); diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h b/examples/energy-management-app/energy-management-common/common/include/EnergyManagementAppCommonMain.h similarity index 54% rename from examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h rename to examples/energy-management-app/energy-management-common/common/include/EnergyManagementAppCommonMain.h index ac5cc5000e..1a9ff734b6 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h +++ b/examples/energy-management-app/energy-management-common/common/include/EnergyManagementAppCommonMain.h @@ -19,5 +19,21 @@ #pragma once #include +#include +#include +#include +#include +// This app is configured by default with EP1 for EVSE and EP2 for WaterHeater, with only one endpoint +// enabled. On linux, there's a command line argument (--application) to dynamically enable +// "evse|water-heater", i.e. EP1 or EP2. On other platforms, it's a build time definition (#define). +chip::EndpointId GetEnergyDeviceEndpointId(); + +// The DEM Delegate is used for the TestEventTriggers chip::app::Clusters::DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate(); + +void EvseApplicationInit(); +void EvseApplicationShutdown(); + +void WaterHeaterApplicationInit(); +void WaterHeaterApplicationShutdown(); diff --git a/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp b/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp new file mode 100644 index 0000000000..e35dbf7b05 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp @@ -0,0 +1,410 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "EnergyManagementAppCommonMain.h" +#include "EnergyManagementAppCmdLineOptions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::DataModel; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::DeviceEnergyManagement; +using namespace chip::app::Clusters::ElectricalPowerMeasurement; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement; +using namespace chip::app::Clusters::PowerTopology; +using namespace chip::app::Clusters::WaterHeaterManagement; + +namespace { + +std::unique_ptr gDEMDelegate; +std::unique_ptr gDEMInstance; +std::unique_ptr gEPMDelegate; +std::unique_ptr gEPMInstance; +std::unique_ptr gPTDelegate; +std::unique_ptr gPTInstance; +// Electrical Energy Measurement cluster uses ember to initialise +std::unique_ptr gEEMAttrAccess; +bool gCommonClustersInitialized = false; + +/* + * @brief Creates a Delegate and Instance for PowerTopology clusters + * + * The Instance is a container around the Delegate, so + * create the Delegate first, then wrap it in the Instance + * Then call the Instance->Init() to register the attribute and command handlers + */ +CHIP_ERROR PowerTopologyInit(chip::EndpointId endpointId) +{ + CHIP_ERROR err; + + if (gPTDelegate || gPTInstance) + { + ChipLogError(AppServer, "PowerTopology Instance or Delegate already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + gPTDelegate = std::make_unique(); + if (!gPTDelegate) + { + ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Delegate"); + return CHIP_ERROR_NO_MEMORY; + } + + gPTInstance = std::make_unique( + EndpointId(endpointId), *gPTDelegate, BitMask(PowerTopology::Feature::kNodeTopology), + BitMask(0)); + + if (!gPTInstance) + { + ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Instance"); + gPTDelegate.reset(); + return CHIP_ERROR_NO_MEMORY; + } + + err = gPTInstance->Init(); /* Register Attribute & Command handlers */ + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Init failed on gPTInstance"); + gPTInstance.reset(); + gPTDelegate.reset(); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PowerTopologyShutdown() +{ + /* Do this in the order Instance first, then delegate + * Ensure we call the Instance->Shutdown to free attribute & command handlers first + */ + if (gPTInstance) + { + /* deregister attribute & command handlers */ + gPTInstance->Shutdown(); + gPTInstance.reset(); + } + + if (gPTDelegate) + { + gPTDelegate.reset(); + } + + return CHIP_NO_ERROR; +} + +/* + * @brief Creates a Delegate and Instance for Electrical Power Measurement cluster + * + * The Instance is a container around the Delegate, so + * create the Delegate first, then wrap it in the Instance + * Then call the Instance->Init() to register the attribute and command handlers + */ +CHIP_ERROR ElectricalPowerMeasurementInit(chip::EndpointId endpointId) +{ + CHIP_ERROR err; + + if (gEPMDelegate || gEPMInstance) + { + ChipLogError(AppServer, "EPM Instance or Delegate already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + gEPMDelegate = std::make_unique(); + if (!gEPMDelegate) + { + ChipLogError(AppServer, "Failed to allocate memory for EPM Delegate"); + return CHIP_ERROR_NO_MEMORY; + } + + /* Manufacturer may optionally not support all features, commands & attributes */ + /* Turning on all optional features and attributes for test certification purposes */ + gEPMInstance = std::make_unique( + EndpointId(endpointId), *gEPMDelegate, + BitMask( + ElectricalPowerMeasurement::Feature::kDirectCurrent, ElectricalPowerMeasurement::Feature::kAlternatingCurrent, + ElectricalPowerMeasurement::Feature::kPolyphasePower, ElectricalPowerMeasurement::Feature::kHarmonics, + ElectricalPowerMeasurement::Feature::kPowerQuality), + BitMask( + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRanges, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeVoltage, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeActiveCurrent, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactiveCurrent, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentCurrent, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactivePower, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentPower, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSVoltage, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSCurrent, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSPower, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeFrequency, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributePowerFactor, + ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeNeutralCurrent)); + + if (!gEPMInstance) + { + ChipLogError(AppServer, "Failed to allocate memory for EPM Instance"); + gEPMDelegate.reset(); + return CHIP_ERROR_NO_MEMORY; + } + + err = gEPMInstance->Init(); /* Register Attribute & Command handlers */ + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Init failed on gEPMInstance"); + gEPMInstance.reset(); + gEPMDelegate.reset(); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ElectricalPowerMeasurementShutdown() +{ + /* Do this in the order Instance first, then delegate + * Ensure we call the Instance->Shutdown to free attribute & command handlers first + */ + if (gEPMInstance) + { + /* deregister attribute & command handlers */ + gEPMInstance->Shutdown(); + gEPMInstance.reset(); + } + + if (gEPMDelegate) + { + gEPMDelegate.reset(); + } + + return CHIP_NO_ERROR; +} + +/* + * @brief Creates a Delegate and Instance for DEM + * + * The Instance is a container around the Delegate, so + * create the Delegate first, then wrap it in the Instance + * Then call the Instance->Init() to register the attribute and command handlers + */ +CHIP_ERROR DeviceEnergyManagementInit(chip::EndpointId endpointId) +{ + if (gDEMDelegate || gDEMInstance) + { + ChipLogError(AppServer, "DEM Instance or Delegate already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + gDEMDelegate = std::make_unique(); + if (!gDEMDelegate) + { + ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementDelegate"); + return CHIP_ERROR_NO_MEMORY; + } + + chip::BitMask featureMap = GetFeatureMapFromCmdLine(); + + /* Manufacturer may optionally not support all features, commands & attributes */ + gDEMInstance = std::make_unique(endpointId, *gDEMDelegate, featureMap); + + if (!gDEMInstance) + { + ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementManager"); + gDEMDelegate.reset(); + return CHIP_ERROR_NO_MEMORY; + } + + gDEMDelegate->SetDeviceEnergyManagementInstance(*gDEMInstance); + + CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */ + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Init failed on gDEMInstance"); + gDEMInstance.reset(); + gDEMDelegate.reset(); + return err; + } + + return CHIP_NO_ERROR; +} + +void DeviceEnergyManagementShutdown() +{ + /* Do this in the order Instance first, then delegate + * Ensure we call the Instance->Shutdown to free attribute & command handlers first + */ + if (gDEMInstance) + { + /* deregister attribute & command handlers */ + gDEMInstance->Shutdown(); + gDEMInstance.reset(); + } + if (gDEMDelegate) + { + gDEMDelegate.reset(); + } +} + +CHIP_ERROR EnergyManagementCommonClustersInit(chip::EndpointId endpointId) +{ + if (!gCommonClustersInitialized) + { + DeviceEnergyManagementInit(endpointId); + ElectricalPowerMeasurementInit(endpointId); + PowerTopologyInit(endpointId); + } + VerifyOrReturnError(gDEMDelegate && gDEMInstance, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(gEPMDelegate && gEPMInstance, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(gPTDelegate && gPTInstance, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(gEEMAttrAccess, CHIP_ERROR_INCORRECT_STATE); + gCommonClustersInitialized = true; + return CHIP_NO_ERROR; +} + +} // namespace + +void emberAfElectricalEnergyMeasurementClusterInitCallback(chip::EndpointId endpointId) +{ + /* emberAfElectricalEnergyMeasurementClusterInitCallback() is called for all endpoints + that include the EEM endpoint (even the one we disable dynamically). So here, we only + proceed when it's called for the right endpoint determined by GetEnergyDeviceEndpointId(). + */ + if (endpointId != GetEnergyDeviceEndpointId()) + { + return; + } + + VerifyOrDie(!gEEMAttrAccess); // Ensure it's not initialized yet. + + gEEMAttrAccess = std::make_unique( + BitMask( + ElectricalEnergyMeasurement::Feature::kImportedEnergy, ElectricalEnergyMeasurement::Feature::kExportedEnergy, + ElectricalEnergyMeasurement::Feature::kCumulativeEnergy, ElectricalEnergyMeasurement::Feature::kPeriodicEnergy), + BitMask( + ElectricalEnergyMeasurement::OptionalAttributes::kOptionalAttributeCumulativeEnergyReset)); + + // Create an accuracy entry which is between +/-0.5 and +/- 5% across the range of all possible energy readings + ElectricalEnergyMeasurement::Structs::MeasurementAccuracyRangeStruct::Type energyAccuracyRanges[] = { + { .rangeMin = 0, + .rangeMax = 1'000'000'000'000'000, // 1 million Mwh + .percentMax = MakeOptional(static_cast(500)), + .percentMin = MakeOptional(static_cast(50)) } + }; + + ElectricalEnergyMeasurement::Structs::MeasurementAccuracyStruct::Type accuracy = { + .measurementType = MeasurementTypeEnum::kElectricalEnergy, + .measured = true, + .minMeasuredValue = 0, + .maxMeasuredValue = 1'000'000'000'000'000, // 1 million Mwh + .accuracyRanges = + DataModel::List(energyAccuracyRanges) + }; + + // Example of setting CumulativeEnergyReset structure - for now set these to 0 + // but the manufacturer may want to store these in non volatile storage for timestamp (based on epoch_s) + ElectricalEnergyMeasurement::Structs::CumulativeEnergyResetStruct::Type resetStruct = { + .importedResetTimestamp = MakeOptional(MakeNullable(static_cast(0))), + .exportedResetTimestamp = MakeOptional(MakeNullable(static_cast(0))), + .importedResetSystime = MakeOptional(MakeNullable(static_cast(0))), + .exportedResetSystime = MakeOptional(MakeNullable(static_cast(0))), + }; + + if (gEEMAttrAccess) + { + gEEMAttrAccess->Init(); + + SetMeasurementAccuracy(endpointId, accuracy); + SetCumulativeReset(endpointId, MakeOptional(resetStruct)); + } +} + +DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate() +{ + VerifyOrDieWithMsg(gDEMDelegate.get() != nullptr, AppServer, "DEM Delegate is null"); + + return gDEMDelegate.get(); +} + +void EvseApplicationInit() +{ + auto endpointId = GetEnergyDeviceEndpointId(); + VerifyOrDie(EnergyManagementCommonClustersInit(endpointId) == CHIP_NO_ERROR); + VerifyOrDie(EnergyEvseInit(endpointId) == CHIP_NO_ERROR); + VerifyOrDie(EVSEManufacturerInit(endpointId, *gEPMInstance.get(), *gPTInstance.get(), *gDEMInstance.get(), + *gDEMDelegate.get()) == CHIP_NO_ERROR); +} + +void EvseApplicationShutdown() +{ + ChipLogDetail(AppServer, "Energy Management App (EVSE): EvseApplicationShutdown()"); + + /* Shutdown in reverse order that they were created */ + EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */ + PowerTopologyShutdown(); /* Free the PowerTopology */ + ElectricalPowerMeasurementShutdown(); /* Free the Electrical Power Measurement */ + EnergyEvseShutdown(); /* Free the EnergyEvse */ + DeviceEnergyManagementShutdown(); /* Free the DEM */ + + Clusters::DeviceEnergyManagementMode::Shutdown(); + Clusters::EnergyEvseMode::Shutdown(); +} + +void WaterHeaterApplicationInit() +{ + auto endpointId = GetEnergyDeviceEndpointId(); + VerifyOrDie(EnergyManagementCommonClustersInit(endpointId) == CHIP_NO_ERROR); + VerifyOrDie(WhmApplicationInit(endpointId) == CHIP_NO_ERROR); + + /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ + gDEMDelegate->SetESAState(ESAStateEnum::kOnline); + gDEMDelegate->SetESAType(ESATypeEnum::kWaterHeating); + gDEMDelegate->SetDEMManufacturerDelegate(*GetWhmManufacturer()); + + // Set the abs min and max power + gDEMDelegate->SetAbsMinPower(1200000); // 1.2KW + gDEMDelegate->SetAbsMaxPower(7600000); // 7.6KW +} + +void WaterHeaterApplicationShutdown() +{ + ChipLogDetail(AppServer, "Energy Management App (WaterHeater): WaterHeaterShutdown()"); + + /* Shutdown in reverse order that they were created */ + PowerTopologyShutdown(); /* Free the PowerTopology */ + ElectricalPowerMeasurementShutdown(); /* Free the Energy Meter */ + DeviceEnergyManagementShutdown(); /* Free the DEM */ + WhmApplicationShutdown(); + + Clusters::DeviceEnergyManagementMode::Shutdown(); + Clusters::WaterHeaterMode::Shutdown(); +} diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp index 58258b73cd..23ed2afe1b 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp +++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp @@ -16,9 +16,10 @@ * limitations under the License. */ -#include #include +#include #include +#include #include @@ -28,19 +29,22 @@ using namespace chip; using namespace chip::app; using namespace chip::app::Clusters; using namespace chip::app::Clusters::DeviceEnergyManagement; +namespace { -static constexpr uint16_t MAX_SLOTS = 10; -static constexpr uint16_t MAX_POWER_ADJUSTMENTS = 5; +constexpr uint16_t MAX_SLOTS = 10; +constexpr uint16_t MAX_POWER_ADJUSTMENTS = 5; -static chip::app::Clusters::DeviceEnergyManagement::Structs::SlotStruct::Type sSlots[MAX_SLOTS]; -static chip::app::Clusters::DeviceEnergyManagement::Structs::ForecastStruct::Type sForecastStruct; -static chip::app::DataModel::Nullable sForecast; +chip::app::Clusters::DeviceEnergyManagement::Structs::SlotStruct::Type sSlots[MAX_SLOTS]; +chip::app::Clusters::DeviceEnergyManagement::Structs::ForecastStruct::Type sForecastStruct; +chip::app::DataModel::Nullable sForecast; -static chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustStruct::Type sPowerAdjustments[MAX_POWER_ADJUSTMENTS]; -static chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustCapabilityStruct::Type sPowerAdjustCapabilityStruct; -static chip::app::DataModel::Nullable +chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustStruct::Type sPowerAdjustments[MAX_POWER_ADJUSTMENTS]; +chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustCapabilityStruct::Type sPowerAdjustCapabilityStruct; +chip::app::DataModel::Nullable sPowerAdjustmentCapability; +} // namespace + CHIP_ERROR ConfigureForecast(uint16_t numSlots) { uint32_t chipEpoch = 0; diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp index d993e5c163..330c0b0e38 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp +++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/device-energy-management-mode.cpp @@ -16,19 +16,27 @@ * limitations under the License. */ +#include +#include #include #include using namespace chip::app::Clusters; using namespace chip::app::Clusters::DeviceEnergyManagementMode; +using namespace chip::app::Clusters::DeviceEnergyManagement; + using chip::Protocols::InteractionModel::Status; template using List = chip::app::DataModel::List; using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::Type; +namespace { + static std::unique_ptr gDeviceEnergyManagementModeDelegate; static std::unique_ptr gDeviceEnergyManagementModeInstance; +} // namespace + CHIP_ERROR DeviceEnergyManagementModeDelegate::Init() { return CHIP_NO_ERROR; @@ -77,11 +85,6 @@ CHIP_ERROR DeviceEnergyManagementModeDelegate::GetModeTagsByIndex(uint8_t modeIn return CHIP_NO_ERROR; } -ModeBase::Instance * DeviceEnergyManagementMode::Instance() -{ - return gDeviceEnergyManagementModeInstance.get(); -} - void DeviceEnergyManagementMode::Shutdown() { gDeviceEnergyManagementModeInstance.reset(); @@ -90,6 +93,16 @@ void DeviceEnergyManagementMode::Shutdown() void emberAfDeviceEnergyManagementModeClusterInitCallback(chip::EndpointId endpointId) { + /* emberAfDeviceEnergyManagementModeClusterInitCallback() is called for all endpoints + that include this cluster (even the one we disable dynamically). So here, we only + proceed when it's called for the right endpoint determined by GetEnergyDeviceEndpointId() + (a cmd line argument on linux or #define on other platforms). + */ + if (endpointId != GetEnergyDeviceEndpointId()) + { + return; + } + VerifyOrDie(!gDeviceEnergyManagementModeDelegate && !gDeviceEnergyManagementModeInstance); gDeviceEnergyManagementModeDelegate = std::make_unique(); gDeviceEnergyManagementModeInstance = std::make_unique(gDeviceEnergyManagementModeDelegate.get(), diff --git a/examples/energy-management-app/energy-management-common/energy-evse/include/EVSEManufacturerImpl.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EVSEManufacturerImpl.h index c802cf8e04..4f8c9530ca 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/include/EVSEManufacturerImpl.h +++ b/examples/energy-management-app/energy-management-common/energy-evse/include/EVSEManufacturerImpl.h @@ -117,7 +117,7 @@ class EVSEManufacturer : public DEMManufacturerDelegate /** * @brief Called at start up to apply hardware settings */ - CHIP_ERROR Init(); + CHIP_ERROR Init(chip::EndpointId powerSourceEndpointId); /** * @brief Called at shutdown @@ -143,7 +143,7 @@ class EVSEManufacturer : public DEMManufacturerDelegate /** * @brief Allows a client application to initialise the PowerSource cluster */ - CHIP_ERROR InitializePowerSourceCluster(); + CHIP_ERROR InitializePowerSourceCluster(chip::EndpointId endpointId); /** * @brief Allows a client application to send in power readings into the system diff --git a/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h index 07dce510e9..a959267bea 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h +++ b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h @@ -18,16 +18,18 @@ #pragma once +#include +#include +#include +#include #include -void EvseApplicationInit(); -void EvseApplicationShutdown(); +CHIP_ERROR EnergyEvseInit(chip::EndpointId endpointId); +CHIP_ERROR EnergyEvseShutdown(); -CHIP_ERROR DeviceEnergyManagementInit(); -CHIP_ERROR DeviceEnergyManagementShutdown(); - -CHIP_ERROR EnergyMeterInit(); -CHIP_ERROR EnergyMeterShutdown(); - -CHIP_ERROR PowerTopologyInit(); -CHIP_ERROR PowerTopologyShutdown(); +CHIP_ERROR EVSEManufacturerInit(chip::EndpointId powerSourceEndpointId, + chip::app::Clusters::ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance & epmInstance, + chip::app::Clusters::PowerTopology::PowerTopologyInstance & ptInstance, + chip::app::Clusters::DeviceEnergyManagementManager & demInstance, + chip::app::Clusters::DeviceEnergyManagement::DeviceEnergyManagementDelegate & demDelegate); +CHIP_ERROR EVSEManufacturerShutdown(); diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp index 0cb5a0fe98..372a6472d2 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp @@ -47,7 +47,7 @@ using namespace chip::app::Clusters::PowerSource::Attributes; using Protocols::InteractionModel::Status; -CHIP_ERROR EVSEManufacturer::Init() +CHIP_ERROR EVSEManufacturer::Init(chip::EndpointId powerSourceEndpointId) { /* Manufacturers should modify this to do any custom initialisation */ @@ -63,7 +63,7 @@ CHIP_ERROR EVSEManufacturer::Init() ReturnErrorOnFailure(InitializePowerMeasurementCluster()); - ReturnErrorOnFailure(InitializePowerSourceCluster()); + ReturnErrorOnFailure(InitializePowerSourceCluster(powerSourceEndpointId)); DeviceEnergyManagementDelegate * dem = GetEvseManufacturer()->GetDEMDelegate(); VerifyOrReturnLogError(dem != nullptr, CHIP_ERROR_UNINITIALIZED); @@ -352,31 +352,30 @@ CHIP_ERROR EVSEManufacturer::InitializePowerMeasurementCluster() /** * @brief Allows a client application to initialise the PowerSource cluster */ -CHIP_ERROR EVSEManufacturer::InitializePowerSourceCluster() +CHIP_ERROR EVSEManufacturer::InitializePowerSourceCluster(chip::EndpointId endpointId) { Protocols::InteractionModel::Status status; - status = PowerSource::Attributes::Status::Set(EndpointId(0) /*RootNode*/, PowerSourceStatusEnum::kActive); + status = PowerSource::Attributes::Status::Set(endpointId, PowerSourceStatusEnum::kActive); VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); - status = - PowerSource::Attributes::FeatureMap::Set(EndpointId(0 /*RootNode*/), static_cast(PowerSource::Feature::kWired)); + status = PowerSource::Attributes::FeatureMap::Set(endpointId, static_cast(PowerSource::Feature::kWired)); VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); - status = PowerSource::Attributes::WiredNominalVoltage::Set(EndpointId(0 /*RootNode*/), 230'000); // 230V in mv + status = PowerSource::Attributes::WiredNominalVoltage::Set(endpointId, 230'000); // 230V in mv VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); - status = PowerSource::Attributes::WiredMaximumCurrent::Set(EndpointId(0 /*RootNode*/), 32'000); // 32A in mA + status = PowerSource::Attributes::WiredMaximumCurrent::Set(endpointId, 32'000); // 32A in mA VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); - status = PowerSource::Attributes::WiredCurrentType::Set(EndpointId(0 /*RootNode*/), PowerSource::WiredCurrentTypeEnum::kAc); + status = PowerSource::Attributes::WiredCurrentType::Set(endpointId, PowerSource::WiredCurrentTypeEnum::kAc); VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); - status = PowerSource::Attributes::Description::Set(EndpointId(0 /*RootNode*/), CharSpan::fromCharString("Primary Mains Power")); + status = PowerSource::Attributes::Description::Set(endpointId, CharSpan::fromCharString("Primary Mains Power")); VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); - chip::EndpointId endpointArray[] = { 1 /* EVSE Endpoint */ }; + chip::EndpointId endpointArray[] = { endpointId }; Span endpointList = Span(endpointArray); // Note per API - we do not need to maintain the span after the SetEndpointList has been called // since it takes a copy (see power-source-server.cpp) - PowerSourceServer::Instance().SetEndpointList(0 /* Root Node */, endpointList); + PowerSourceServer::Instance().SetEndpointList(endpointId, endpointList); return CHIP_NO_ERROR; } diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp index 8e900c0948..8c3383db33 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -31,115 +33,30 @@ #include #include #include -#include #include #include #include -#define ENERGY_EVSE_ENDPOINT 1 - using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; using namespace chip::app::Clusters; -using namespace chip::app::Clusters::EnergyEvse; using namespace chip::app::Clusters::DeviceEnergyManagement; using namespace chip::app::Clusters::ElectricalPowerMeasurement; using namespace chip::app::Clusters::ElectricalEnergyMeasurement; +using namespace chip::app::Clusters::EnergyEvse; using namespace chip::app::Clusters::PowerTopology; static std::unique_ptr gEvseDelegate; static std::unique_ptr gEvseTargetsDelegate; static std::unique_ptr gEvseInstance; -static std::unique_ptr gDEMDelegate; -static std::unique_ptr gDEMInstance; static std::unique_ptr gEvseManufacturer; -static std::unique_ptr gEPMDelegate; -static std::unique_ptr gEPMInstance; -// Electrical Energy Measurement cluster uses ember to initialise -static std::unique_ptr gEEMAttrAccess; - -static std::unique_ptr gPTDelegate; -static std::unique_ptr gPTInstance; EVSEManufacturer * EnergyEvse::GetEvseManufacturer() { return gEvseManufacturer.get(); } -DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate() -{ - VerifyOrDieWithMsg(gDEMDelegate.get() != nullptr, AppServer, "DEM Delegate is null"); - - return gDEMDelegate.get(); -} - -/* - * @brief Creates a Delegate and Instance for DEM - * - * The Instance is a container around the Delegate, so - * create the Delegate first, then wrap it in the Instance - * Then call the Instance->Init() to register the attribute and command handlers - */ -CHIP_ERROR DeviceEnergyManagementInit() -{ - if (gDEMDelegate || gDEMInstance) - { - ChipLogError(AppServer, "DEM Instance or Delegate already exist."); - return CHIP_ERROR_INCORRECT_STATE; - } - - gDEMDelegate = std::make_unique(); - if (!gDEMDelegate) - { - ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementDelegate"); - return CHIP_ERROR_NO_MEMORY; - } - - BitMask featureMap = GetFeatureMapFromCmdLine(); - - /* Manufacturer may optionally not support all features, commands & attributes */ - gDEMInstance = std::make_unique(EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, featureMap); - - if (!gDEMInstance) - { - ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementManager"); - gDEMDelegate.reset(); - return CHIP_ERROR_NO_MEMORY; - } - - gDEMDelegate->SetDeviceEnergyManagementInstance(*gDEMInstance); - - CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */ - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Init failed on gDEMInstance"); - gDEMInstance.reset(); - gDEMDelegate.reset(); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR DeviceEnergyManagementShutdown() -{ - /* Do this in the order Instance first, then delegate - * Ensure we call the Instance->Shutdown to free attribute & command handlers first - */ - if (gDEMInstance) - { - /* deregister attribute & command handlers */ - gDEMInstance->Shutdown(); - gDEMInstance.reset(); - } - if (gDEMDelegate) - { - gDEMDelegate.reset(); - } - return CHIP_NO_ERROR; -} - /* * @brief Creates a Delegate and Instance for EVSE cluster * @@ -147,7 +64,7 @@ CHIP_ERROR DeviceEnergyManagementShutdown() * create the Delegate first, then wrap it in the Instance * Then call the Instance->Init() to register the attribute and command handlers */ -CHIP_ERROR EnergyEvseInit() +CHIP_ERROR EnergyEvseInit(chip::EndpointId endpointId) { CHIP_ERROR err; @@ -174,7 +91,7 @@ CHIP_ERROR EnergyEvseInit() /* Manufacturer may optionally not support all features, commands & attributes */ gEvseInstance = std::make_unique( - EndpointId(ENERGY_EVSE_ENDPOINT), *gEvseDelegate, + EndpointId(endpointId), *gEvseDelegate, BitMask(EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kRfid), BitMask(EnergyEvse::OptionalAttributes::kSupportsUserMaximumChargingCurrent, EnergyEvse::OptionalAttributes::kSupportsRandomizationWindow, @@ -232,160 +149,6 @@ CHIP_ERROR EnergyEvseShutdown() return CHIP_NO_ERROR; } -/* - * @brief Creates a Delegate and Instance for PowerTopology clusters - * - * The Instance is a container around the Delegate, so - * create the Delegate first, then wrap it in the Instance - * Then call the Instance->Init() to register the attribute and command handlers - */ -CHIP_ERROR PowerTopologyInit() -{ - CHIP_ERROR err; - - if (gPTDelegate || gPTInstance) - { - ChipLogError(AppServer, "PowerTopology Instance or Delegate already exist."); - return CHIP_ERROR_INCORRECT_STATE; - } - - gPTDelegate = std::make_unique(); - if (!gPTDelegate) - { - ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Delegate"); - return CHIP_ERROR_NO_MEMORY; - } - - gPTInstance = - std::make_unique(EndpointId(ENERGY_EVSE_ENDPOINT), *gPTDelegate, - BitMask(PowerTopology::Feature::kNodeTopology), - BitMask(0)); - - if (!gPTInstance) - { - ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Instance"); - gPTDelegate.reset(); - return CHIP_ERROR_NO_MEMORY; - } - - err = gPTInstance->Init(); /* Register Attribute & Command handlers */ - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Init failed on gPTInstance"); - gPTInstance.reset(); - gPTDelegate.reset(); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR PowerTopologyShutdown() -{ - /* Do this in the order Instance first, then delegate - * Ensure we call the Instance->Shutdown to free attribute & command handlers first - */ - if (gPTInstance) - { - /* deregister attribute & command handlers */ - gPTInstance->Shutdown(); - gPTInstance.reset(); - } - - if (gPTDelegate) - { - gPTDelegate.reset(); - } - - return CHIP_NO_ERROR; -} - -/* - * @brief Creates a Delegate and Instance for Electrical Power/Energy Measurement clusters - * - * The Instance is a container around the Delegate, so - * create the Delegate first, then wrap it in the Instance - * Then call the Instance->Init() to register the attribute and command handlers - */ -CHIP_ERROR EnergyMeterInit() -{ - CHIP_ERROR err; - - if (gEPMDelegate || gEPMInstance) - { - ChipLogError(AppServer, "EPM Instance or Delegate already exist."); - return CHIP_ERROR_INCORRECT_STATE; - } - - gEPMDelegate = std::make_unique(); - if (!gEPMDelegate) - { - ChipLogError(AppServer, "Failed to allocate memory for EPM Delegate"); - return CHIP_ERROR_NO_MEMORY; - } - - /* Manufacturer may optionally not support all features, commands & attributes */ - /* Turning on all optional features and attributes for test certification purposes */ - gEPMInstance = std::make_unique( - EndpointId(ENERGY_EVSE_ENDPOINT), *gEPMDelegate, - BitMask( - ElectricalPowerMeasurement::Feature::kDirectCurrent, ElectricalPowerMeasurement::Feature::kAlternatingCurrent, - ElectricalPowerMeasurement::Feature::kPolyphasePower, ElectricalPowerMeasurement::Feature::kHarmonics, - ElectricalPowerMeasurement::Feature::kPowerQuality), - BitMask( - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRanges, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeVoltage, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeActiveCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactiveCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactivePower, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentPower, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSVoltage, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSPower, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeFrequency, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributePowerFactor, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeNeutralCurrent)); - - if (!gEPMInstance) - { - ChipLogError(AppServer, "Failed to allocate memory for EPM Instance"); - gEPMDelegate.reset(); - return CHIP_ERROR_NO_MEMORY; - } - - err = gEPMInstance->Init(); /* Register Attribute & Command handlers */ - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Init failed on gEPMInstance"); - gEPMInstance.reset(); - gEPMDelegate.reset(); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR EnergyMeterShutdown() -{ - /* Do this in the order Instance first, then delegate - * Ensure we call the Instance->Shutdown to free attribute & command handlers first - */ - if (gEPMInstance) - { - /* deregister attribute & command handlers */ - gEPMInstance->Shutdown(); - gEPMInstance.reset(); - } - - if (gEPMDelegate) - { - gEPMDelegate.reset(); - } - - return CHIP_NO_ERROR; -} - /* * @brief Creates a EVSEManufacturer class to hold the EVSE & DEM clusters * @@ -393,7 +156,9 @@ CHIP_ERROR EnergyMeterShutdown() * create the Delegate first, then wrap it in the Instance * Then call the Instance->Init() to register the attribute and command handlers */ -CHIP_ERROR EVSEManufacturerInit() +CHIP_ERROR EVSEManufacturerInit(chip::EndpointId powerSourceEndpointId, ElectricalPowerMeasurementInstance & epmInstance, + PowerTopologyInstance & ptInstance, DeviceEnergyManagementManager & demInstance, + DeviceEnergyManagementDelegate & demDelegate) { CHIP_ERROR err; @@ -404,18 +169,17 @@ CHIP_ERROR EVSEManufacturerInit() } /* Now create EVSEManufacturer */ - gEvseManufacturer = - std::make_unique(gEvseInstance.get(), gEPMInstance.get(), gPTInstance.get(), gDEMInstance.get()); + gEvseManufacturer = std::make_unique(gEvseInstance.get(), &epmInstance, &ptInstance, &demInstance); if (!gEvseManufacturer) { ChipLogError(AppServer, "Failed to allocate memory for EvseManufacturer"); return CHIP_ERROR_NO_MEMORY; } - gDEMDelegate.get()->SetDEMManufacturerDelegate(*gEvseManufacturer.get()); + demDelegate.SetDEMManufacturerDelegate(*gEvseManufacturer.get()); /* Call Manufacturer specific init */ - err = gEvseManufacturer->Init(); + err = gEvseManufacturer->Init(powerSourceEndpointId); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Init failed on gEvseManufacturer"); @@ -437,104 +201,3 @@ CHIP_ERROR EVSEManufacturerShutdown() return CHIP_NO_ERROR; } - -void EvseApplicationInit() -{ - if (DeviceEnergyManagementInit() != CHIP_NO_ERROR) - { - return; - } - - if (EnergyEvseInit() != CHIP_NO_ERROR) - { - DeviceEnergyManagementShutdown(); - return; - } - - if (EnergyMeterInit() != CHIP_NO_ERROR) - { - DeviceEnergyManagementShutdown(); - EnergyEvseShutdown(); - return; - } - - if (PowerTopologyInit() != CHIP_NO_ERROR) - { - EVSEManufacturerShutdown(); - DeviceEnergyManagementShutdown(); - EnergyEvseShutdown(); - EnergyMeterShutdown(); - return; - } - - /* Do this last so that the instances for other clusters can be wrapped inside */ - if (EVSEManufacturerInit() != CHIP_NO_ERROR) - { - DeviceEnergyManagementShutdown(); - EnergyEvseShutdown(); - EnergyMeterShutdown(); - return; - } -} - -void EvseApplicationShutdown() -{ - ChipLogDetail(AppServer, "Energy Management App (EVSE): ApplicationShutdown()"); - - /* Shutdown in reverse order that they were created */ - EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */ - PowerTopologyShutdown(); /* Free the PowerTopology */ - EnergyMeterShutdown(); /* Free the Energy Meter */ - EnergyEvseShutdown(); /* Free the EnergyEvse */ - DeviceEnergyManagementShutdown(); /* Free the DEM */ - - Clusters::DeviceEnergyManagementMode::Shutdown(); - Clusters::EnergyEvseMode::Shutdown(); -} - -void emberAfElectricalEnergyMeasurementClusterInitCallback(chip::EndpointId endpointId) -{ - VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. - VerifyOrDie(!gEEMAttrAccess); - - gEEMAttrAccess = std::make_unique( - BitMask( - ElectricalEnergyMeasurement::Feature::kImportedEnergy, ElectricalEnergyMeasurement::Feature::kExportedEnergy, - ElectricalEnergyMeasurement::Feature::kCumulativeEnergy, ElectricalEnergyMeasurement::Feature::kPeriodicEnergy), - BitMask( - ElectricalEnergyMeasurement::OptionalAttributes::kOptionalAttributeCumulativeEnergyReset)); - - // Create an accuracy entry which is between +/-0.5 and +/- 5% across the range of all possible energy readings - ElectricalEnergyMeasurement::Structs::MeasurementAccuracyRangeStruct::Type energyAccuracyRanges[] = { - { .rangeMin = 0, - .rangeMax = 1'000'000'000'000'000, // 1 million Mwh - .percentMax = MakeOptional(static_cast(500)), - .percentMin = MakeOptional(static_cast(50)) } - }; - - ElectricalEnergyMeasurement::Structs::MeasurementAccuracyStruct::Type accuracy = { - .measurementType = MeasurementTypeEnum::kElectricalEnergy, - .measured = true, - .minMeasuredValue = 0, - .maxMeasuredValue = 1'000'000'000'000'000, // 1 million Mwh - .accuracyRanges = - DataModel::List(energyAccuracyRanges) - }; - - // Example of setting CumulativeEnergyReset structure - for now set these to 0 - // but the manufacturer may want to store these in non volatile storage for timestamp (based on epoch_s) - ElectricalEnergyMeasurement::Structs::CumulativeEnergyResetStruct::Type resetStruct = { - .importedResetTimestamp = MakeOptional(MakeNullable(static_cast(0))), - .exportedResetTimestamp = MakeOptional(MakeNullable(static_cast(0))), - .importedResetSystime = MakeOptional(MakeNullable(static_cast(0))), - .exportedResetSystime = MakeOptional(MakeNullable(static_cast(0))), - }; - - if (gEEMAttrAccess) - { - gEEMAttrAccess->Init(); - - SetMeasurementAccuracy(endpointId, accuracy); - SetCumulativeReset(endpointId, MakeOptional(resetStruct)); - } -} diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.matter b/examples/energy-management-app/energy-management-common/energy-management-app.matter index a3c2b9f58b..bdcbe117c8 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.matter +++ b/examples/energy-management-app/energy-management-common/energy-management-app.matter @@ -2416,7 +2416,6 @@ endpoint 0 { server cluster AccessControl { callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; @@ -2448,7 +2447,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 3; + ram attribute clusterRevision default = 4; } server cluster LocalizationConfiguration { @@ -2478,21 +2477,6 @@ endpoint 0 { ram attribute clusterRevision default = 1; } - server cluster PowerSource { - ram attribute status; - ram attribute order; - ram attribute description; - ram attribute wiredCurrentType; - ram attribute wiredNominalVoltage; - ram attribute wiredMaximumCurrent; - callback attribute endpointList; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 2; - } - server cluster GeneralCommissioning { ram attribute breadcrumb default = 0x0000000000000000; callback attribute basicCommissioningInfo; @@ -2503,7 +2487,7 @@ endpoint 0 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -2605,8 +2589,10 @@ endpoint 0 { } } endpoint 1 { + device type ma_powersource = 17, version 1; device type ma_electricalsensor = 1296, version 1; device type energy_evse = 1292, version 1; + device type device_energy_management = 1293, version 1; server cluster Identify { @@ -2616,7 +2602,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 4; + ram attribute clusterRevision default = 5; handle command Identify; handle command TriggerEffect; @@ -2634,6 +2620,21 @@ endpoint 1 { callback attribute clusterRevision; } + server cluster PowerSource { + ram attribute status; + ram attribute order; + ram attribute description; + ram attribute wiredCurrentType; + ram attribute wiredNominalVoltage; + ram attribute wiredMaximumCurrent; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 3; + } + server cluster ElectricalPowerMeasurement { callback attribute powerMode; callback attribute numberOfMeasurementTypes; @@ -2677,23 +2678,6 @@ endpoint 1 { ram attribute clusterRevision default = 1; } - server cluster WaterHeaterManagement { - callback attribute heaterTypes; - callback attribute heatDemand; - callback attribute tankVolume; - callback attribute estimatedHeatRequired; - callback attribute tankPercentage; - callback attribute boostState; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - callback attribute featureMap; - callback attribute clusterRevision; - - handle command Boost; - handle command CancelBoost; - } - server cluster DeviceEnergyManagement { emits event PowerAdjustStart; emits event PowerAdjustEnd; @@ -2751,7 +2735,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command GetTargetsResponse; handle command Disable; @@ -2778,12 +2762,137 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ChangeToMode; handle command ChangeToModeResponse; } + server cluster DeviceEnergyManagementMode { + callback attribute supportedModes; + callback attribute currentMode; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 2; + + handle command ChangeToMode; + handle command ChangeToModeResponse; + } +} +endpoint 2 { + device type ma_electricalsensor = 1296, version 1; + device type device_energy_management = 1293, version 1; + device type ma_waterheater = 1295, version 1; + + + server cluster Identify { + ram attribute identifyTime default = 0x0; + ram attribute identifyType default = 0x00; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 5; + + handle command Identify; + } + + server cluster Descriptor { + callback attribute deviceTypeList; + callback attribute serverList; + callback attribute clientList; + callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + } + + server cluster ElectricalPowerMeasurement { + callback attribute powerMode; + callback attribute numberOfMeasurementTypes; + callback attribute accuracy; + callback attribute ranges; + callback attribute voltage; + callback attribute activeCurrent; + callback attribute reactiveCurrent; + callback attribute apparentCurrent; + callback attribute activePower; + callback attribute reactivePower; + callback attribute apparentPower; + callback attribute RMSVoltage; + callback attribute RMSCurrent; + callback attribute RMSPower; + callback attribute frequency; + callback attribute harmonicCurrents; + callback attribute harmonicPhases; + callback attribute powerFactor; + callback attribute neutralCurrent; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster ElectricalEnergyMeasurement { + callback attribute accuracy; + callback attribute cumulativeEnergyImported; + callback attribute cumulativeEnergyExported; + callback attribute periodicEnergyImported; + callback attribute periodicEnergyExported; + callback attribute cumulativeEnergyReset; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + + server cluster WaterHeaterManagement { + callback attribute heaterTypes; + callback attribute heatDemand; + callback attribute tankVolume; + callback attribute estimatedHeatRequired; + callback attribute tankPercentage; + callback attribute boostState; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command Boost; + handle command CancelBoost; + } + + server cluster DeviceEnergyManagement { + callback attribute ESAType; + callback attribute ESACanGenerate; + callback attribute ESAState; + callback attribute absMinPower; + callback attribute absMaxPower; + callback attribute powerAdjustmentCapability; + callback attribute forecast; + callback attribute optOutState; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 4; + } + + server cluster PowerTopology { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster WaterHeaterMode { callback attribute supportedModes; callback attribute currentMode; @@ -2804,7 +2913,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ChangeToMode; handle command ChangeToModeResponse; diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.zap b/examples/energy-management-app/energy-management-common/energy-management-app.zap index 17a539dbf1..ee365c7ec5 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.zap +++ b/examples/energy-management-app/energy-management-common/energy-management-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,14 +41,16 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -165,22 +167,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -255,22 +241,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "Extension", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "SubjectsPerAccessControlEntry", "code": 2, @@ -351,22 +321,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -713,22 +667,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -771,7 +709,7 @@ "storageOption": "RAM", "singleton": 1, "bounded": 0, - "defaultValue": "3", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -851,22 +789,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -973,22 +895,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1079,22 +985,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1146,115 +1036,117 @@ ] }, { - "name": "Power Source", - "code": 47, + "name": "General Commissioning", + "code": 48, "mfgCode": null, - "define": "POWER_SOURCE_CLUSTER", + "define": "GENERAL_COMMISSIONING_CLUSTER", "side": "server", "enabled": 1, - "attributes": [ + "commands": [ { - "name": "Status", + "name": "ArmFailSafe", "code": 0, "mfgCode": null, - "side": "server", - "type": "PowerSourceStatusEnum", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "Order", + "name": "ArmFailSafeResponse", "code": 1, "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "server", + "isIncoming": 0, + "isEnabled": 1 }, { - "name": "Description", + "name": "SetRegulatoryConfig", "code": 2, "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "WiredCurrentType", + "name": "SetRegulatoryConfigResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "CommissioningComplete", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CommissioningCompleteResponse", "code": 5, "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "Breadcrumb", + "code": 0, + "mfgCode": null, "side": "server", - "type": "WiredCurrentTypeEnum", + "type": "int64u", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0x0000000000000000", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "WiredNominalVoltage", - "code": 7, + "name": "BasicCommissioningInfo", + "code": 1, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "BasicCommissioningInfo", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "WiredMaximumCurrent", - "code": 8, + "name": "RegulatoryConfig", + "code": 2, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "RegulatoryLocationTypeEnum", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "EndpointList", - "code": 31, + "name": "LocationCapability", + "code": 3, "mfgCode": null, "side": "server", - "type": "array", + "type": "RegulatoryLocationTypeEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -1266,11 +1158,11 @@ "reportableChange": 0 }, { - "name": "GeneratedCommandList", - "code": 65528, + "name": "SupportsConcurrentConnection", + "code": 4, "mfgCode": null, "side": "server", - "type": "array", + "type": "boolean", "included": 1, "storageOption": "External", "singleton": 0, @@ -1282,8 +1174,8 @@ "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1298,8 +1190,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -1364,146 +1256,112 @@ ] }, { - "name": "General Commissioning", - "code": 48, + "name": "Network Commissioning", + "code": 49, "mfgCode": null, - "define": "GENERAL_COMMISSIONING_CLUSTER", + "define": "NETWORK_COMMISSIONING_CLUSTER", "side": "server", "enabled": 1, - "commands": [ + "attributes": [ { - "name": "ArmFailSafe", + "name": "MaxNetworks", "code": 0, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "ArmFailSafeResponse", + "name": "Networks", "code": 1, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "SetRegulatoryConfig", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "SetRegulatoryConfigResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "CommissioningComplete", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CommissioningCompleteResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "Breadcrumb", - "code": 0, - "mfgCode": null, "side": "server", - "type": "int64u", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0x0000000000000000", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "BasicCommissioningInfo", - "code": 1, + "name": "InterfaceEnabled", + "code": 4, "mfgCode": null, "side": "server", - "type": "BasicCommissioningInfo", + "type": "boolean", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "RegulatoryConfig", - "code": 2, + "name": "LastNetworkingStatus", + "code": 5, "mfgCode": null, "side": "server", - "type": "RegulatoryLocationTypeEnum", + "type": "NetworkCommissioningStatusEnum", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "LocationCapability", - "code": 3, + "name": "LastNetworkID", + "code": 6, "mfgCode": null, "side": "server", - "type": "RegulatoryLocationTypeEnum", + "type": "octet_string", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "SupportsConcurrentConnection", - "code": 4, + "name": "LastConnectErrorValue", + "code": 7, "mfgCode": null, "side": "server", - "type": "boolean", + "type": "int32s", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "GeneratedCommandList", - "code": 65528, + "name": "SupportedWiFiBands", + "code": 8, "mfgCode": null, "side": "server", "type": "array", @@ -1518,8 +1376,8 @@ "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1534,8 +1392,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -1600,120 +1458,98 @@ ] }, { - "name": "Network Commissioning", - "code": 49, + "name": "General Diagnostics", + "code": 51, "mfgCode": null, - "define": "NETWORK_COMMISSIONING_CLUSTER", + "define": "GENERAL_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, - "attributes": [ + "commands": [ { - "name": "MaxNetworks", + "name": "TestEventTrigger", "code": 0, "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "Networks", + "name": "TimeSnapshot", "code": 1, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "InterfaceEnabled", - "code": 4, + "name": "TimeSnapshotResponse", + "code": 2, "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ { - "name": "LastNetworkingStatus", - "code": 5, + "name": "NetworkInterfaces", + "code": 0, "mfgCode": null, "side": "server", - "type": "NetworkCommissioningStatusEnum", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "LastNetworkID", - "code": 6, + "name": "RebootCount", + "code": 1, "mfgCode": null, "side": "server", - "type": "octet_string", + "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "LastConnectErrorValue", - "code": 7, + "name": "UpTime", + "code": 2, "mfgCode": null, "side": "server", - "type": "int32s", + "type": "int64u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "SupportedWiFiBands", + "name": "TestEventTriggersEnabled", "code": 8, "mfgCode": null, "side": "server", - "type": "array", + "type": "boolean", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -1751,22 +1587,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1790,10 +1610,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -1806,10 +1626,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -1818,15 +1638,15 @@ ] }, { - "name": "General Diagnostics", - "code": 51, + "name": "Administrator Commissioning", + "code": 60, "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "TestEventTrigger", + "name": "OpenCommissioningWindow", "code": 0, "mfgCode": null, "source": "client", @@ -1834,29 +1654,21 @@ "isEnabled": 1 }, { - "name": "TimeSnapshot", - "code": 1, + "name": "RevokeCommissioning", + "code": 2, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, - { - "name": "TimeSnapshotResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 } ], "attributes": [ { - "name": "NetworkInterfaces", + "name": "WindowStatus", "code": 0, "mfgCode": null, "side": "server", - "type": "array", + "type": "CommissioningWindowStatusEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -1868,11 +1680,11 @@ "reportableChange": 0 }, { - "name": "RebootCount", + "name": "AdminFabricIndex", "code": 1, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "fabric_idx", "included": 1, "storageOption": "External", "singleton": 0, @@ -1884,11 +1696,11 @@ "reportableChange": 0 }, { - "name": "UpTime", + "name": "AdminVendorId", "code": 2, "mfgCode": null, "side": "server", - "type": "int64u", + "type": "vendor_id", "included": 1, "storageOption": "External", "singleton": 0, @@ -1900,199 +1712,11 @@ "reportableChange": 0 }, { - "name": "TestEventTriggersEnabled", - "code": 8, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ] - }, - { - "name": "Administrator Commissioning", - "code": 60, - "mfgCode": null, - "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "OpenCommissioningWindow", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "RevokeCommissioning", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "WindowStatus", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "CommissioningWindowStatusEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AdminFabricIndex", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "fabric_idx", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AdminVendorId", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "vendor_id", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -2119,22 +1743,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2419,22 +2027,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2639,22 +2231,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2714,29 +2290,50 @@ "code": 1292, "profileId": 259, "label": "Energy EVSE", - "name": "Energy EVSE" + "name": "Energy EVSE", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 1292, "profileId": 259, "label": "Energy EVSE", - "name": "Energy EVSE" + "name": "Energy EVSE", + "deviceTypeOrder": 0 }, { "code": 1296, "profileId": 259, "label": "MA-electricalsensor", - "name": "MA-electricalsensor" + "name": "MA-electricalsensor", + "deviceTypeOrder": 1 + }, + { + "code": 1293, + "profileId": 259, + "label": "Device Energy Management", + "name": "Device Energy Management", + "deviceTypeOrder": 2 + }, + { + "code": 17, + "profileId": 259, + "label": "MA-powersource", + "name": "MA-powersource", + "deviceTypeOrder": 3 } ], "deviceVersions": [ + 1, + 1, 1, 1 ], "deviceIdentifiers": [ 1292, - 1296 + 1296, + 1293, + 17 ], "deviceTypeName": "Energy EVSE", "deviceTypeCode": 1292, @@ -2832,22 +2429,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2890,7 +2471,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "5", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3003,8 +2584,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -3019,8 +2600,194 @@ "reportableChange": 0 }, { - "name": "AttributeList", - "code": 65531, + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredCurrentType", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "WiredCurrentTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredNominalVoltage", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredMaximumCurrent", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -3041,10 +2808,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3057,10 +2824,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3412,22 +3179,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3614,22 +3365,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3697,16 +3432,16 @@ ] }, { - "name": "Water Heater Management", - "code": 148, + "name": "Device Energy Management", + "code": 152, "mfgCode": null, - "define": "WATER_HEATER_MANAGEMENT_CLUSTER", + "define": "DEVICE_ENERGY_MANAGEMENT_CLUSTER", "side": "server", "enabled": 1, "apiMaturity": "provisional", "commands": [ { - "name": "Boost", + "name": "PowerAdjustRequest", "code": 0, "mfgCode": null, "source": "client", @@ -3714,241 +3449,20 @@ "isEnabled": 1 }, { - "name": "CancelBoost", + "name": "CancelPowerAdjustRequest", "code": 1, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - } - ], - "attributes": [ + }, { - "name": "HeaterTypes", - "code": 0, + "name": "StartTimeAdjustRequest", + "code": 2, "mfgCode": null, - "side": "server", - "type": "WaterHeaterHeatSourceBitmap", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "HeatDemand", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "WaterHeaterHeatSourceBitmap", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "TankVolume", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "EstimatedHeatRequired", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "energy_mwh", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "TankPercentage", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "percent", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "BoostState", - "code": 5, - "mfgCode": null, - "side": "server", - "type": "BoostStateEnum", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AcceptedCommandList", - "code": 65529, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "AttributeList", - "code": 65531, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "server", - "type": "bitmap32", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - } - ] - }, - { - "name": "Device Energy Management", - "code": 152, - "mfgCode": null, - "define": "DEVICE_ENERGY_MANAGEMENT_CLUSTER", - "side": "server", - "enabled": 1, - "apiMaturity": "provisional", - "commands": [ - { - "name": "PowerAdjustRequest", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CancelPowerAdjustRequest", - "code": 1, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "StartTimeAdjustRequest", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { "name": "PauseRequest", @@ -4152,22 +3666,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -4551,7 +4049,1526 @@ "code": 64, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SessionDuration", + "code": 65, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "SessionEnergyCharged", + "code": 66, + "mfgCode": null, + "side": "server", + "type": "energy_mwh", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "EVConnected", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "EVNotDetected", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "EnergyTransferStarted", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "EnergyTransferStopped", + "code": 3, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "Fault", + "code": 4, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "RFID", + "code": 5, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, + { + "name": "Power Topology", + "code": 156, + "mfgCode": null, + "define": "POWER_TOPOLOGY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Energy EVSE Mode", + "code": 157, + "mfgCode": null, + "define": "ENERGY_EVSE_MODE_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "ChangeToMode", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ChangeToModeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "SupportedModes", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentMode", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Device Energy Management Mode", + "code": 159, + "mfgCode": null, + "define": "DEVICE_ENERGY_MANAGEMENT_MODE_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "ChangeToMode", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ChangeToModeResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "SupportedModes", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentMode", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 3, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 1295, + "profileId": 259, + "label": "MA-waterheater", + "name": "MA-waterheater", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 1295, + "profileId": 259, + "label": "MA-waterheater", + "name": "MA-waterheater", + "deviceTypeOrder": 0 + }, + { + "code": 1296, + "profileId": 259, + "label": "MA-electricalsensor", + "name": "MA-electricalsensor", + "deviceTypeOrder": 1 + }, + { + "code": 1293, + "profileId": 259, + "label": "Device Energy Management", + "name": "Device Energy Management", + "deviceTypeOrder": 2 + } + ], + "deviceVersions": [ + 1, + 1, + 1 + ], + "deviceIdentifiers": [ + 1295, + 1296, + 1293 + ], + "deviceTypeName": "MA-waterheater", + "deviceTypeCode": 1295, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "5", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Descriptor", + "code": 29, + "mfgCode": null, + "define": "DESCRIPTOR_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "DeviceTypeList", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ServerList", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClientList", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PartsList", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Electrical Power Measurement", + "code": 144, + "mfgCode": null, + "define": "ELECTRICAL_POWER_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "PowerMode", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerModeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NumberOfMeasurementTypes", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Accuracy", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Ranges", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Voltage", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "voltage_mv", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActiveCurrent", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "amperage_ma", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ReactiveCurrent", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "amperage_ma", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ApparentCurrent", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "amperage_ma", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ActivePower", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ReactivePower", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ApparentPower", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RMSVoltage", + "code": 11, + "mfgCode": null, + "side": "server", + "type": "voltage_mv", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RMSCurrent", + "code": 12, + "mfgCode": null, + "side": "server", + "type": "amperage_ma", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RMSPower", + "code": 13, + "mfgCode": null, + "side": "server", + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Frequency", + "code": 14, + "mfgCode": null, + "side": "server", + "type": "int64s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HarmonicCurrents", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HarmonicPhases", + "code": 16, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PowerFactor", + "code": 17, + "mfgCode": null, + "side": "server", + "type": "int64s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "NeutralCurrent", + "code": 18, + "mfgCode": null, + "side": "server", + "type": "amperage_ma", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Electrical Energy Measurement", + "code": 145, + "mfgCode": null, + "define": "ELECTRICAL_ENERGY_MEASUREMENT_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Accuracy", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "MeasurementAccuracyStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CumulativeEnergyImported", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "EnergyMeasurementStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CumulativeEnergyExported", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "EnergyMeasurementStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeriodicEnergyImported", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "EnergyMeasurementStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "PeriodicEnergyExported", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "EnergyMeasurementStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CumulativeEnergyReset", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "CumulativeEnergyResetStruct", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, + { + "name": "Water Heater Management", + "code": 148, + "mfgCode": null, + "define": "WATER_HEATER_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "Boost", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "CancelBoost", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "HeaterTypes", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "WaterHeaterHeatSourceBitmap", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "HeatDemand", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "WaterHeaterHeatSourceBitmap", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TankVolume", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -4563,11 +5580,11 @@ "reportableChange": 0 }, { - "name": "SessionDuration", - "code": 65, + "name": "EstimatedHeatRequired", + "code": 3, "mfgCode": null, "side": "server", - "type": "elapsed_s", + "type": "energy_mwh", "included": 1, "storageOption": "External", "singleton": 0, @@ -4579,11 +5596,11 @@ "reportableChange": 0 }, { - "name": "SessionEnergyCharged", - "code": 66, + "name": "TankPercentage", + "code": 4, "mfgCode": null, "side": "server", - "type": "energy_mwh", + "type": "percent", "included": 1, "storageOption": "External", "singleton": 0, @@ -4595,11 +5612,11 @@ "reportableChange": 0 }, { - "name": "GeneratedCommandList", - "code": 65528, + "name": "BoostState", + "code": 5, "mfgCode": null, "side": "server", - "type": "array", + "type": "BoostStateEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -4611,8 +5628,8 @@ "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -4627,8 +5644,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -4681,75 +5698,96 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 } - ], - "events": [ + ] + }, + { + "name": "Device Energy Management", + "code": 152, + "mfgCode": null, + "define": "DEVICE_ENERGY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "attributes": [ { - "name": "EVConnected", + "name": "ESAType", "code": 0, "mfgCode": null, "side": "server", - "included": 1 + "type": "ESATypeEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "EVNotDetected", + "name": "ESACanGenerate", "code": 1, "mfgCode": null, "side": "server", - "included": 1 + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "EnergyTransferStarted", + "name": "ESAState", "code": 2, "mfgCode": null, "side": "server", - "included": 1 + "type": "ESAStateEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "EnergyTransferStopped", + "name": "AbsMinPower", "code": 3, "mfgCode": null, "side": "server", - "included": 1 + "type": "power_mw", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "Fault", + "name": "AbsMaxPower", "code": 4, "mfgCode": null, "side": "server", - "included": 1 - }, - { - "name": "RFID", - "code": 5, - "mfgCode": null, - "side": "server", - "included": 1 - } - ] - }, - { - "name": "Power Topology", - "code": 156, - "mfgCode": null, - "define": "POWER_TOPOLOGY_CLUSTER", - "side": "server", - "enabled": 1, - "attributes": [ - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", + "type": "power_mw", "included": 1, "storageOption": "External", "singleton": 0, @@ -4761,11 +5799,11 @@ "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "PowerAdjustmentCapability", + "code": 5, "mfgCode": null, "side": "server", - "type": "array", + "type": "PowerAdjustCapabilityStruct", "included": 1, "storageOption": "External", "singleton": 0, @@ -4777,11 +5815,11 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "Forecast", + "code": 6, "mfgCode": null, "side": "server", - "type": "array", + "type": "ForecastStruct", "included": 1, "storageOption": "External", "singleton": 0, @@ -4793,11 +5831,11 @@ "reportableChange": 0 }, { - "name": "AttributeList", - "code": 65531, + "name": "OptOutState", + "code": 7, "mfgCode": null, "side": "server", - "type": "array", + "type": "OptOutStateEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -4809,11 +5847,11 @@ "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -4825,52 +5863,24 @@ "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 - } - ] - }, - { - "name": "Energy EVSE Mode", - "code": 157, - "mfgCode": null, - "define": "ENERGY_EVSE_MODE_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "ChangeToMode", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 }, { - "name": "ChangeToModeResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "SupportedModes", - "code": 0, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -4885,11 +5895,11 @@ "reportableChange": 0 }, { - "name": "CurrentMode", - "code": 1, + "name": "FeatureMap", + "code": 65532, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "bitmap32", "included": 1, "storageOption": "External", "singleton": 0, @@ -4901,24 +5911,34 @@ "reportableChange": 0 }, { - "name": "GeneratedCommandList", - "code": 65528, + "name": "ClusterRevision", + "code": 65533, "mfgCode": null, "side": "server", - "type": "array", + "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 - }, + } + ] + }, + { + "name": "Power Topology", + "code": 156, + "mfgCode": null, + "define": "POWER_TOPOLOGY_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ { - "name": "AcceptedCommandList", - "code": 65529, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -4933,8 +5953,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -5088,22 +6108,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -5245,22 +6249,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -5303,7 +6291,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -5330,6 +6318,14 @@ "endpointId": 1, "networkId": 0, "parentEndpointIdentifier": null + }, + { + "endpointTypeName": "Anonymous Endpoint Type", + "endpointTypeIndex": 2, + "profileId": 259, + "endpointId": 2, + "networkId": 0, + "parentEndpointIdentifier": 0 } ] } \ No newline at end of file diff --git a/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h b/examples/energy-management-app/energy-management-common/energy-reporting/include/ElectricalSensorInit.h similarity index 55% rename from examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h rename to examples/energy-management-app/energy-management-common/energy-reporting/include/ElectricalSensorInit.h index 819ff9e4d1..6e0c38bb7d 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h +++ b/examples/energy-management-app/energy-management-common/energy-reporting/include/ElectricalSensorInit.h @@ -18,15 +18,16 @@ #pragma once -namespace chip { -namespace app { -namespace Clusters { -namespace WaterHeaterManagement { +#include +#include +#include +#include -void FullWhmApplicationInit(); -void FullWhmApplicationShutdown(); +chip::app::Clusters::PowerTopology::PowerTopologyInstance * GetPTInstance(); +chip::app::Clusters::ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * GetEPMInstance(); -} // namespace WaterHeaterManagement -} // namespace Clusters -} // namespace app -} // namespace chip +CHIP_ERROR PowerTopologyInit(chip::EndpointId endpointId); +CHIP_ERROR PowerTopologyShutdown(); + +CHIP_ERROR ElectricalPowerMeasurementInit(chip::EndpointId endpointId); +CHIP_ERROR ElectricalPowerMeasurementShutdown(); diff --git a/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp b/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp index bffe3c900d..8fab0e2a7d 100644 --- a/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp +++ b/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp @@ -16,8 +16,8 @@ * limitations under the License. */ -#include #include +#include #include #include diff --git a/examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h b/examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h index 34f04d8cbb..d0fa8d97f5 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h +++ b/examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h @@ -25,7 +25,7 @@ namespace app { namespace Clusters { namespace WaterHeaterManagement { -CHIP_ERROR WhmApplicationInit(); +CHIP_ERROR WhmApplicationInit(EndpointId endpointId); CHIP_ERROR WhmApplicationShutdown(); } // namespace WaterHeaterManagement diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp deleted file mode 100644 index 0c8e44ac7c..0000000000 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * All rights reserved. - * - * 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. - */ - -#include "EnergyManagementAppCmdLineOptions.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace chip { -namespace app { -namespace Clusters { -namespace WaterHeaterManagement { - -void FullWhmApplicationInit() -{ - ReturnOnFailure(WhmApplicationInit()); - - if (DeviceEnergyManagementInit() != CHIP_NO_ERROR) - { - WhmApplicationShutdown(); - return; - } - - if (EnergyMeterInit() != CHIP_NO_ERROR) - { - DeviceEnergyManagementShutdown(); - WhmApplicationShutdown(); - return; - } - - if (PowerTopologyInit() != CHIP_NO_ERROR) - { - EnergyMeterShutdown(); - DeviceEnergyManagementShutdown(); - WhmApplicationShutdown(); - return; - } - - /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ - - GetDEMDelegate()->SetESAState(ESAStateEnum::kOnline); - GetDEMDelegate()->SetESAType(ESATypeEnum::kWaterHeating); - GetDEMDelegate()->SetDEMManufacturerDelegate(*GetWhmManufacturer()); - - // Set the abs min and max power - GetDEMDelegate()->SetAbsMinPower(1200000); // 1.2KW - GetDEMDelegate()->SetAbsMaxPower(7600000); // 7.6KW -} - -void FullWhmApplicationShutdown() -{ - ChipLogDetail(AppServer, "Energy Management App (WaterHeater): ApplicationShutdown()"); - - /* Shutdown in reverse order that they were created */ - PowerTopologyShutdown(); /* Free the PowerTopology */ - EnergyMeterShutdown(); /* Free the Energy Meter */ - DeviceEnergyManagementShutdown(); /* Free the DEM */ - WhmApplicationShutdown(); - - Clusters::DeviceEnergyManagementMode::Shutdown(); - Clusters::WaterHeaterMode::Shutdown(); -} - -} // namespace WaterHeaterManagement -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp index 79a64d5226..edab8b7cd1 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp @@ -307,6 +307,7 @@ int16_t WaterHeaterManagementDelegate::GetActiveTargetWaterTemperature() const // Note, in practise the actual heating is likely to be controlled by the thermostat's occupiedHeatingSetpoint most of the // time, and the TemporarySetpoint (if not null) would be overiding the thermostat's occupiedHeatingSetpoint. // However, this code doesn't rely upon the thermostat cluster. + // TODO: Implement Thermostat Cluster temperature handling. It's mandatory to be spec conformant. int16_t targetTemperature = (mBoostState == BoostStateEnum::kActive && mBoostTemporarySetpoint.HasValue()) ? mBoostTemporarySetpoint.Value() : mTargetWaterTemperature; diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp index 038e332bd3..b53da3c7d6 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp @@ -24,8 +24,6 @@ #include #include -static constexpr int WHM_ENDPOINT = 1; - using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; @@ -53,7 +51,7 @@ WhmManufacturer * GetWhmManufacturer() * create the Delegate first, then wrap it in the Instance * Then call the Instance->Init() to register the attribute and command handlers */ -CHIP_ERROR WhmInit() +CHIP_ERROR WhmInit(EndpointId endpointId) { CHIP_ERROR err; @@ -63,7 +61,7 @@ CHIP_ERROR WhmInit() return CHIP_ERROR_INCORRECT_STATE; } - gWhmDelegate = std::make_unique(WHM_ENDPOINT); + gWhmDelegate = std::make_unique(endpointId); if (!gWhmDelegate) { ChipLogError(AppServer, "Failed to allocate memory for WaterHeaterManagementDelegate"); @@ -72,7 +70,7 @@ CHIP_ERROR WhmInit() /* Manufacturer may optionally not support all features, commands & attributes */ gWhmInstance = std::make_unique( - EndpointId(WHM_ENDPOINT), *gWhmDelegate, BitMask(Feature::kEnergyManagement, Feature::kTankPercent)); + EndpointId(endpointId), *gWhmDelegate, BitMask(Feature::kEnergyManagement, Feature::kTankPercent)); if (!gWhmInstance) { ChipLogError(AppServer, "Failed to allocate memory for WaterHeaterManagementInstance"); @@ -167,9 +165,9 @@ CHIP_ERROR WhmManufacturerShutdown() return CHIP_NO_ERROR; } -CHIP_ERROR WhmApplicationInit() +CHIP_ERROR WhmApplicationInit(EndpointId endpointId) { - ReturnErrorOnFailure(WhmInit()); + ReturnErrorOnFailure(WhmInit(endpointId)); /* Do this last so that the instances for other clusters can be wrapped inside */ ReturnErrorOnFailure(WhmManufacturerInit()); diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp index 9c4121fb70..76f61b72b9 100755 --- a/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp @@ -24,9 +24,12 @@ using chip::Protocols::InteractionModel::Status; template using List = chip::app::DataModel::List; using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::Type; +namespace { -static ExampleWaterHeaterModeDelegate * gWaterHeaterModeDelegate = nullptr; -static ModeBase::Instance * gWaterHeaterModeInstance = nullptr; +ExampleWaterHeaterModeDelegate * gWaterHeaterModeDelegate = nullptr; +ModeBase::Instance * gWaterHeaterModeInstance = nullptr; + +} // namespace CHIP_ERROR ExampleWaterHeaterModeDelegate::Init() { @@ -99,7 +102,6 @@ void emberAfWaterHeaterModeClusterInitCallback(chip::EndpointId endpointId) { VerifyOrDie(gWaterHeaterModeDelegate == nullptr && gWaterHeaterModeInstance == nullptr); gWaterHeaterModeDelegate = new WaterHeaterMode::ExampleWaterHeaterModeDelegate; - gWaterHeaterModeInstance = - new ModeBase::Instance(gWaterHeaterModeDelegate, endpointId, WaterHeaterMode::Id, chip::to_underlying(Feature::kOnOff)); + gWaterHeaterModeInstance = new ModeBase::Instance(gWaterHeaterModeDelegate, endpointId, WaterHeaterMode::Id, 0); gWaterHeaterModeInstance->Init(); } diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp index d235fa4291..9e1dff9b43 100644 --- a/examples/energy-management-app/esp32/main/main.cpp +++ b/examples/energy-management-app/esp32/main/main.cpp @@ -17,15 +17,8 @@ #include "DeviceCallbacks.h" -#if CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE -#include -#endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE - -#if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE -#include -#endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE - #include "esp_log.h" +#include #include #include #include @@ -43,8 +36,10 @@ #include "nvs_flash.h" #include "shell_extension/launch.h" #include "shell_extension/openthread_cli_register.h" +#include #include #include +#include #include #include #include @@ -80,6 +75,7 @@ using namespace ::chip::Credentials; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; using namespace chip::app::Clusters::WaterHeaterManagement; +using namespace chip::app::Clusters::DeviceEnergyManagement; #if CONFIG_ENABLE_ESP_INSIGHTS_TRACE extern const char insights_auth_key_start[] asm("_binary_insights_auth_key_txt_start"); @@ -92,6 +88,10 @@ static AppDeviceCallbacks EchoCallbacks; static DeviceCallbacksDelegate sAppDeviceCallbacksDelegate; namespace { + +constexpr chip::EndpointId kEvseEndpoint = 1; +constexpr chip::EndpointId kWaterHeaterEndpoint = 2; + #if CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider; #endif // CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER @@ -156,15 +156,29 @@ chip::BitMask GetFeatureMapFromCmdLine() #error Cannot define CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE and CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE #endif +EndpointId GetEnergyDeviceEndpointId() +{ +#if defined(CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE) + return kWaterHeaterEndpoint; +#else + return kEvseEndpoint; +#endif +} + void ApplicationInit() { ESP_LOGD(TAG, "Energy Management App: ApplicationInit()"); #if CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE + EvseApplicationInit(); + // Disable Water Heater Endpoint + emberAfEndpointEnableDisable(kWaterHeaterEndpoint, false); #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE - FullWhmApplicationInit(); + WaterHeaterApplicationInit(); + // Disable EVSE Endpoint + emberAfEndpointEnableDisable(kEvseEndpoint, false); #endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE } @@ -177,7 +191,7 @@ void ApplicationShutdown() #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE - FullWhmApplicationShutdown(); + WaterHeaterApplicationShutdown(); #endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE } diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn index a9d41a1e76..e742c05d69 100644 --- a/examples/energy-management-app/linux/BUILD.gn +++ b/examples/energy-management-app/linux/BUILD.gn @@ -34,6 +34,7 @@ config("includes") { executable("chip-energy-management-app") { sources = [ + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", @@ -51,7 +52,6 @@ executable("chip-energy-management-app") { "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingEventTriggers.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/PowerTopologyDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmInstance.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp", diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp index 7a6312538a..d4cefde1c1 100644 --- a/examples/energy-management-app/linux/main.cpp +++ b/examples/energy-management-app/linux/main.cpp @@ -17,9 +17,10 @@ */ #include -#include -#include +#include +#include #include +#include #include using namespace chip; @@ -39,10 +40,12 @@ static bool EnergyAppOptionHandler(const char * aProgram, chip::ArgParser::Optio constexpr uint16_t kOptionApplication = 0xffd0; constexpr uint16_t kOptionFeatureMap = 0xffd1; -constexpr const char * kEvseApp = "evse"; -constexpr const char * kWhmApp = "water-heater"; - -constexpr const char * kValidApps[] = { kEvseApp, kWhmApp }; +constexpr chip::EndpointId kEvseEndpoint = 1; +constexpr chip::EndpointId kWaterHeaterEndpoint = 2; +constexpr const char * kEvseApp = "evse"; +constexpr const char * kWhmApp = "water-heater"; +constexpr const char * kValidApps[] = { kEvseApp, kWhmApp }; +constexpr EndpointId kValidEndpoints[] = { kEvseEndpoint, kWaterHeaterEndpoint }; // Define the chip::ArgParser command line structures for extending the command line to support the // energy apps @@ -65,11 +68,12 @@ namespace DeviceEnergyManagement { // Keep track of the parsed featureMap option static chip::BitMask sFeatureMap(Feature::kPowerAdjustment, Feature::kPowerForecastReporting, - Feature::kStateForecastReporting, Feature::kStartTimeAdjustment, Feature::kPausable, - Feature::kForecastAdjustment, Feature::kConstraintBasedAdjustment); + Feature::kStartTimeAdjustment, Feature::kPausable, Feature::kForecastAdjustment, + Feature::kConstraintBasedAdjustment); // Make EVSE the default app -static const char * spApp = kEvseApp; +static const char * spApp = kEvseApp; +static EndpointId sAppEndpointId = kEvseEndpoint; chip::BitMask GetFeatureMapFromCmdLine() { @@ -81,6 +85,11 @@ chip::BitMask GetFeatureMapFromCmdLine() } // namespace app } // namespace chip +chip::EndpointId GetEnergyDeviceEndpointId() +{ + return sAppEndpointId; +} + static uint32_t ParseNumber(const char * pString) { uint32_t num = 0; @@ -101,11 +110,15 @@ void ApplicationInit() ChipLogDetail(AppServer, "Energy Management App: ApplicationInit()"); if (strcmp(spApp, kEvseApp) == 0) { + // Disable Water Heater Endpoint + emberAfEndpointEnableDisable(kWaterHeaterEndpoint, false); EvseApplicationInit(); } else if (strcmp(spApp, kWhmApp) == 0) { - FullWhmApplicationInit(); + // Disable EVSE Endpoint + emberAfEndpointEnableDisable(kEvseEndpoint, false); + WaterHeaterApplicationInit(); } else { @@ -118,7 +131,7 @@ void ApplicationShutdown() ChipLogDetail(AppServer, "Energy Management App: ApplicationShutdown()"); EvseApplicationShutdown(); - FullWhmApplicationShutdown(); + WaterHeaterApplicationShutdown(); } static bool EnergyAppOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier, @@ -134,7 +147,8 @@ static bool EnergyAppOptionHandler(const char * aProgram, chip::ArgParser::Optio { if (strcmp(kValidApps[idx], aValue) == 0) { - spApp = kValidApps[idx]; + spApp = kValidApps[idx]; + sAppEndpointId = kValidEndpoints[idx]; break; } } diff --git a/examples/energy-management-app/silabs/BUILD.gn b/examples/energy-management-app/silabs/BUILD.gn index d4a4887cee..1ed8a4473b 100644 --- a/examples/energy-management-app/silabs/BUILD.gn +++ b/examples/energy-management-app/silabs/BUILD.gn @@ -166,6 +166,7 @@ silabs_executable("energy-management-app") { } sources = [ + "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyManagementAppCommonMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", @@ -183,7 +184,6 @@ silabs_executable("energy-management-app") { "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingEventTriggers.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/PowerTopologyDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmInstance.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp", diff --git a/examples/energy-management-app/silabs/src/AppTask.cpp b/examples/energy-management-app/silabs/src/AppTask.cpp index 42069a85b5..f90952ea45 100644 --- a/examples/energy-management-app/silabs/src/AppTask.cpp +++ b/examples/energy-management-app/silabs/src/AppTask.cpp @@ -21,12 +21,7 @@ #include "AppConfig.h" #include "AppEvent.h" #include "LEDWidget.h" -#if SL_MATTER_CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE -#include -#endif -#if SL_CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE -#include -#endif +#include #include #include #include @@ -36,6 +31,7 @@ #include #include #include +#include #include #include @@ -46,6 +42,7 @@ #include +#include #include #ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED @@ -76,8 +73,12 @@ #define APP_EVSE_SWITCH 1 namespace { + LEDWidget sEnergyManagementLED; -} +constexpr chip::EndpointId kEvseEndpoint = 1; +constexpr chip::EndpointId kWaterHeaterEndpoint = 2; + +} // namespace using namespace chip; using namespace chip::app; @@ -130,6 +131,15 @@ chip::BitMask GetFeatureMapFromCmdLine() AppTask AppTask::sAppTask; +EndpointId GetEnergyDeviceEndpointId() +{ +#if defined(SL_CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE) + return kWaterHeaterEndpoint; +#else + return kEvseEndpoint; +#endif +} + void ApplicationInit() { chip::DeviceLayer::PlatformMgr().LockChipStack(); @@ -138,12 +148,16 @@ void ApplicationInit() SILABS_LOG("energy-management-example EVSE starting. featureMap 0x%08lx", DeviceEnergyManagement::sFeatureMap.Raw()); EvseApplicationInit(); + // Disable Water Heater Endpoint + emberAfEndpointEnableDisable(kWaterHeaterEndpoint, false); #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if SL_CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE SILABS_LOG("energy-management-example WaterHeater starting. featureMap 0x%08lx", DeviceEnergyManagement::sFeatureMap.Raw()); - FullWhmApplicationInit(); + WaterHeaterApplicationInit(); + // Disable EVSE Endpoint + emberAfEndpointEnableDisable(kEvseEndpoint, false); #endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE SILABS_LOG("=================================================="); @@ -158,7 +172,7 @@ void ApplicationShutdown() #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if SL_CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE - FullWhmApplicationShutdown(); + WaterHeaterApplicationShutdown(); #endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE chip::DeviceLayer::PlatformMgr().UnlockChipStack(); } diff --git a/src/python_testing/TC_EWATERHTR_2_1.py b/src/python_testing/TC_EWATERHTR_2_1.py index 82c9e93dad..c0eeaaea3d 100644 --- a/src/python_testing/TC_EWATERHTR_2_1.py +++ b/src/python_testing/TC_EWATERHTR_2_1.py @@ -35,7 +35,7 @@ # --discriminator 1234 # --passcode 20202021 # --hex-arg enableKey:000102030405060708090a0b0c0d0e0f -# --endpoint 1 +# --endpoint 2 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true diff --git a/src/python_testing/TC_EWATERHTR_2_2.py b/src/python_testing/TC_EWATERHTR_2_2.py index 2c639a7c71..91ef524459 100644 --- a/src/python_testing/TC_EWATERHTR_2_2.py +++ b/src/python_testing/TC_EWATERHTR_2_2.py @@ -35,7 +35,7 @@ # --discriminator 1234 # --passcode 20202021 # --hex-arg enableKey:000102030405060708090a0b0c0d0e0f -# --endpoint 1 +# --endpoint 2 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true diff --git a/src/python_testing/TC_EWATERHTR_2_3.py b/src/python_testing/TC_EWATERHTR_2_3.py index 8833a3c58a..ff84a0ffbf 100644 --- a/src/python_testing/TC_EWATERHTR_2_3.py +++ b/src/python_testing/TC_EWATERHTR_2_3.py @@ -34,7 +34,7 @@ # --discriminator 1234 # --passcode 20202021 # --hex-arg enableKey:000102030405060708090a0b0c0d0e0f -# --endpoint 1 +# --endpoint 2 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true diff --git a/src/python_testing/TC_WHM_1_2.py b/src/python_testing/TC_WHM_1_2.py index 0ce34ee831..302c53dffc 100644 --- a/src/python_testing/TC_WHM_1_2.py +++ b/src/python_testing/TC_WHM_1_2.py @@ -31,7 +31,7 @@ # --discriminator 1234 # --passcode 20202021 # --hex-arg enableKey:000102030405060708090a0b0c0d0e0f -# --endpoint 1 +# --endpoint 2 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true diff --git a/src/python_testing/TC_WHM_2_1.py b/src/python_testing/TC_WHM_2_1.py index 7380c7a862..13f4c18957 100644 --- a/src/python_testing/TC_WHM_2_1.py +++ b/src/python_testing/TC_WHM_2_1.py @@ -32,7 +32,7 @@ # --commissioning-method on-network # --discriminator 1234 # --passcode 20202021 -# --endpoint 1 +# --endpoint 2 # --trace-to json:${TRACE_TEST_JSON}.json # --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto # factory-reset: true From 29c264723be6ebfb1564d5f999f96e2f70cbc1e0 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Wed, 27 Nov 2024 19:33:42 -0500 Subject: [PATCH 105/219] [Silabs] General updates and fixes for the Silabs Wi-Fi platforms (#36628) * [SL-UP] Remove two algo design for the wifi retry mechanism (#103) * [SL-UP] Rename ot interval to transport interval (#108) * [SL-UP] Delete unnecessary double abstraction for the wiseconnect power save functions (#109) * [SL-UP] Update spi-multiplex header inclusion (#110) * [SL-UP] Fix Builds after Wi-Fi interface refactor (#111) * [SL-UP] Remove WF200 define duplication to avoid value conflicts at runtime (#126) * fix spacing * restyle * Fix define name * add missing function * Fix wf200 ICD build * Restyled by clang-format * Add debug config * Re added sem check --------- Co-authored-by: Restyled.io --- .../light-switch-app/silabs/openthread.gni | 4 +- examples/lit-icd-app/silabs/openthread.gni | 4 +- examples/lock-app/silabs/openthread.gni | 4 +- .../efr32/project_include/OpenThreadConfig.h | 2 +- examples/platform/silabs/uart.cpp | 2 +- .../silabs/src/RefrigeratorUI.cpp | 6 +- .../smoke-co-alarm-app/silabs/openthread.gni | 4 +- .../thermostat/silabs/src/ThermostatUI.cpp | 6 +- examples/window-app/silabs/openthread.gni | 4 +- .../silabs/CHIPDevicePlatformConfig.h | 4 +- .../silabs/SiWx917/SiWxPlatformInterface.h | 7 +++ .../silabs/multi-ota/OTACustomProcessor.cpp | 7 ++- .../silabs/multi-ota/OTAFirmwareProcessor.cpp | 7 ++- .../multi-ota/OTAMultiImageProcessorImpl.cpp | 7 ++- src/platform/silabs/wifi/BUILD.gn | 13 ++++- .../silabs/wifi/SiWx/WifiInterface.cpp | 54 ++++++----------- .../silabs/wifi/WifiInterfaceAbstraction.cpp | 58 +++++-------------- .../silabs/wifi/WifiInterfaceAbstraction.h | 14 ----- .../silabs/wifi/lwip-support/ethernetif.cpp | 22 +++---- .../silabs/wifi/rs911x/WifiInterface.cpp | 55 +++++++----------- .../silabs/wifi/wf200/WifiInterface.cpp | 17 ++---- .../silabs/wifi/wf200/platform/efr_spi.c | 2 - .../silabs/wifi/wf200/platform/sl_wfx_host.h | 3 + .../silabs/wifi/wf200/platform/wf200_init.c | 1 + src/platform/silabs/wifi/wf200/wf200.gni | 1 - src/platform/silabs/wifi/wfx_msgs.h | 9 +++ third_party/silabs/efr32_sdk.gni | 24 ++------ 27 files changed, 132 insertions(+), 209 deletions(-) diff --git a/examples/light-switch-app/silabs/openthread.gni b/examples/light-switch-app/silabs/openthread.gni index 4ec1c04a92..88dcdef98e 100644 --- a/examples/light-switch-app/silabs/openthread.gni +++ b/examples/light-switch-app/silabs/openthread.gni @@ -36,8 +36,8 @@ chip_subscription_timeout_resumption = false sl_use_subscription_syncing = true # Openthread Configuration flags -sl_ot_idle_interval_ms = 2100000 # 35 minutes Idle Intervals -sl_ot_active_interval_ms = 1000 # 1000ms Active Intervals +sl_transport_idle_interval_ms = 2100000 # 35 minutes Idle Intervals +sl_transport_active_interval_ms = 1000 # 1000ms Active Intervals # ICD Matter Configuration flags sl_idle_mode_duration_s = 1800 # 30min Idle Mode Duration diff --git a/examples/lit-icd-app/silabs/openthread.gni b/examples/lit-icd-app/silabs/openthread.gni index c09176354a..9f38cd9136 100644 --- a/examples/lit-icd-app/silabs/openthread.gni +++ b/examples/lit-icd-app/silabs/openthread.gni @@ -37,8 +37,8 @@ chip_enable_icd_lit = true chip_enable_icd_dsls = true # Openthread Configuration flags -sl_ot_idle_interval_ms = 3600000 # 60mins Idle Polling Interval -sl_ot_active_interval_ms = 1000 # 1000ms Active Polling Interval +sl_transport_idle_interval_ms = 3600000 # 60mins Idle Polling Interval +sl_transport_active_interval_ms = 1000 # 1000ms Active Polling Interval # ICD Matter Configuration flags sl_idle_mode_duration_s = 3600 # 60min Idle Mode Duration diff --git a/examples/lock-app/silabs/openthread.gni b/examples/lock-app/silabs/openthread.gni index 46359c13e8..f9b6888d59 100644 --- a/examples/lock-app/silabs/openthread.gni +++ b/examples/lock-app/silabs/openthread.gni @@ -33,8 +33,8 @@ chip_subscription_timeout_resumption = false sl_use_subscription_syncing = true # Openthread Configuration flags -sl_ot_idle_interval_ms = 5000 # 5s Idle Intervals -sl_ot_active_interval_ms = 500 # 500ms Active Intervals +sl_transport_idle_interval_ms = 5000 # 5s Idle Intervals +sl_transport_active_interval_ms = 500 # 500ms Active Intervals # ICD Matter Configuration flags sl_idle_mode_duration_s = 600 # 10min Idle Mode Duration diff --git a/examples/platform/silabs/efr32/project_include/OpenThreadConfig.h b/examples/platform/silabs/efr32/project_include/OpenThreadConfig.h index ed56c7a578..c0c79c95ac 100644 --- a/examples/platform/silabs/efr32/project_include/OpenThreadConfig.h +++ b/examples/platform/silabs/efr32/project_include/OpenThreadConfig.h @@ -40,7 +40,7 @@ #define OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 0 // In seconds -#define SL_MLE_TIMEOUT_s (SL_OT_IDLE_INTERVAL / 1000) +#define SL_MLE_TIMEOUT_s (SL_TRANSPORT_IDLE_INTERVAL / 1000) // Timeout after 2 missed checkin or 4 mins if sleep interval is too short. #define OPENTHREAD_CONFIG_MLE_CHILD_TIMEOUT_DEFAULT ((SL_MLE_TIMEOUT_s < 120) ? 240 : ((SL_MLE_TIMEOUT_s * 2) + 1)) diff --git a/examples/platform/silabs/uart.cpp b/examples/platform/silabs/uart.cpp index c460554c6a..809c4e53e0 100644 --- a/examples/platform/silabs/uart.cpp +++ b/examples/platform/silabs/uart.cpp @@ -53,7 +53,7 @@ extern "C" { #endif #include "sl_uartdrv_instances.h" #if SL_WIFI -#include "spi_multiplex.h" +#include #endif // SL_WIFI #ifdef SL_CATALOG_UARTDRV_EUSART_PRESENT #include "sl_uartdrv_eusart_vcom_config.h" diff --git a/examples/refrigerator-app/silabs/src/RefrigeratorUI.cpp b/examples/refrigerator-app/silabs/src/RefrigeratorUI.cpp index 655c803f21..f1b7d7698d 100644 --- a/examples/refrigerator-app/silabs/src/RefrigeratorUI.cpp +++ b/examples/refrigerator-app/silabs/src/RefrigeratorUI.cpp @@ -26,10 +26,10 @@ #include "lcd.h" #include -#if SL_WIFI && !defined(SLI_SI91X_MCU_INTERFACE) // Only needed for wifi NCP devices -#include "spi_multiplex.h" -#endif // SL_WIFI +#if SL_WIFI && !defined(SLI_SI91X_MCU_INTERFACE) +#include +#endif // SL_WIFI && !defined(SLI_SI91X_MCU_INTERFACE) // LCD line define constexpr uint8_t kTempLcdInitialX = 30; diff --git a/examples/smoke-co-alarm-app/silabs/openthread.gni b/examples/smoke-co-alarm-app/silabs/openthread.gni index f2a7ab6ed7..a9b6527c41 100644 --- a/examples/smoke-co-alarm-app/silabs/openthread.gni +++ b/examples/smoke-co-alarm-app/silabs/openthread.gni @@ -36,8 +36,8 @@ chip_icd_report_on_active_mode = true chip_enable_icd_lit = true # Openthread Configuration flags -sl_ot_idle_interval_ms = 3600000 # 60mins Idle Polling Interval -sl_ot_active_interval_ms = 1000 # 1000ms Active Polling Interval +sl_transport_idle_interval_ms = 3600000 # 60mins Idle Polling Interval +sl_transport_active_interval_ms = 1000 # 1000ms Active Polling Interval # ICD Matter Configuration flags sl_idle_mode_duration_s = 3600 # 60min Idle Mode Duration diff --git a/examples/thermostat/silabs/src/ThermostatUI.cpp b/examples/thermostat/silabs/src/ThermostatUI.cpp index f82ee36387..4ac0263a0c 100644 --- a/examples/thermostat/silabs/src/ThermostatUI.cpp +++ b/examples/thermostat/silabs/src/ThermostatUI.cpp @@ -25,10 +25,10 @@ #include "glib.h" #include "lcd.h" -#if SL_WIFI && !defined(SLI_SI91X_MCU_INTERFACE) // Only needed for wifi NCP devices -#include "spi_multiplex.h" -#endif // SL_WIFI +#if SL_WIFI && !defined(SLI_SI91X_MCU_INTERFACE) +#include +#endif // SL_WIFI && !defined(SLI_SI91X_MCU_INTERFACE) // LCD line define constexpr uint8_t kTempLcdInitialX = 30; diff --git a/examples/window-app/silabs/openthread.gni b/examples/window-app/silabs/openthread.gni index 47c5860c9f..0736dc61e4 100644 --- a/examples/window-app/silabs/openthread.gni +++ b/examples/window-app/silabs/openthread.gni @@ -33,8 +33,8 @@ chip_subscription_timeout_resumption = false sl_use_subscription_syncing = true # Openthread Configuration flags -sl_ot_idle_interval_ms = 1000 # 1s Idle Intervals -sl_ot_active_interval_ms = 500 # 500ms Active Intervals +sl_transport_idle_interval_ms = 1000 # 1s Idle Intervals +sl_transport_active_interval_ms = 500 # 500ms Active Intervals # ICD Matter Configuration flags sl_idle_mode_duration_s = 600 # 10min Idle Mode Duration diff --git a/src/platform/silabs/CHIPDevicePlatformConfig.h b/src/platform/silabs/CHIPDevicePlatformConfig.h index 7e86c64694..387c9c934b 100644 --- a/src/platform/silabs/CHIPDevicePlatformConfig.h +++ b/src/platform/silabs/CHIPDevicePlatformConfig.h @@ -169,10 +169,10 @@ #if SL_ICD_ENABLED #ifndef CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL -#define CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL chip::System::Clock::Milliseconds32(SL_OT_IDLE_INTERVAL) +#define CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL chip::System::Clock::Milliseconds32(SL_TRANSPORT_IDLE_INTERVAL) #endif // CHIP_DEVICE_CONFIG_ICD_SLOW_POLL_INTERVAL #ifndef CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL -#define CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL chip::System::Clock::Milliseconds32(SL_OT_ACTIVE_INTERVAL) +#define CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL chip::System::Clock::Milliseconds32(SL_TRANSPORT_ACTIVE_INTERVAL) #endif // CHIP_DEVICE_CONFIG_ICD_FAST_POLL_INTERVAL #endif // SL_ICD_ENABLED diff --git a/src/platform/silabs/SiWx917/SiWxPlatformInterface.h b/src/platform/silabs/SiWx917/SiWxPlatformInterface.h index 8589db3b3f..1b654332f1 100644 --- a/src/platform/silabs/SiWx917/SiWxPlatformInterface.h +++ b/src/platform/silabs/SiWx917/SiWxPlatformInterface.h @@ -19,6 +19,12 @@ #include +namespace { +#ifdef ENABLE_CHIP_SHELL +bool ps_requirement_added = false; +#endif // ENABLE_CHIP_SHELL +} // namespace + #ifdef __cplusplus extern "C" { #endif @@ -27,6 +33,7 @@ extern "C" { #include "sl_si91x_button.h" #include "sl_si91x_button_pin_config.h" #include "sl_si91x_driver_gpio.h" +#include "sl_si91x_power_manager.h" /** * @brief invoked when button press event is received when in sleep diff --git a/src/platform/silabs/multi-ota/OTACustomProcessor.cpp b/src/platform/silabs/multi-ota/OTACustomProcessor.cpp index 6b87638adb..852866e94e 100644 --- a/src/platform/silabs/multi-ota/OTACustomProcessor.cpp +++ b/src/platform/silabs/multi-ota/OTACustomProcessor.cpp @@ -22,12 +22,13 @@ #include +#if SL_WIFI +#include +#endif // SL_WIFI + extern "C" { #include "btl_interface.h" #include "sl_core.h" -#if SL_WIFI -#include "spi_multiplex.h" -#endif // SL_WIFI } /// No error, operation OK diff --git a/src/platform/silabs/multi-ota/OTAFirmwareProcessor.cpp b/src/platform/silabs/multi-ota/OTAFirmwareProcessor.cpp index 07dc974dd7..2f1277a311 100644 --- a/src/platform/silabs/multi-ota/OTAFirmwareProcessor.cpp +++ b/src/platform/silabs/multi-ota/OTAFirmwareProcessor.cpp @@ -22,12 +22,13 @@ #include +#if SL_WIFI +#include +#endif // SL_WIFI + extern "C" { #include "btl_interface.h" #include "sl_core.h" -#if SL_WIFI -#include "spi_multiplex.h" -#endif // SL_WIFI } /// No error, operation OK diff --git a/src/platform/silabs/multi-ota/OTAMultiImageProcessorImpl.cpp b/src/platform/silabs/multi-ota/OTAMultiImageProcessorImpl.cpp index 42a9788c28..85859f29fa 100644 --- a/src/platform/silabs/multi-ota/OTAMultiImageProcessorImpl.cpp +++ b/src/platform/silabs/multi-ota/OTAMultiImageProcessorImpl.cpp @@ -30,12 +30,13 @@ using namespace ::chip::DeviceLayer::Internal; static chip::OTAMultiImageProcessorImpl gImageProcessor; +#if SL_WIFI +#include +#endif // SL_WIFI + extern "C" { #include "btl_interface.h" #include "sl_core.h" -#if SL_WIFI -#include "spi_multiplex.h" -#endif // SL_WIFI } namespace chip { diff --git a/src/platform/silabs/wifi/BUILD.gn b/src/platform/silabs/wifi/BUILD.gn index 882a66deb4..db58633599 100644 --- a/src/platform/silabs/wifi/BUILD.gn +++ b/src/platform/silabs/wifi/BUILD.gn @@ -31,6 +31,9 @@ declare_args() { #default Wifi Password chip_default_wifi_psk = "" + + # Argument to enable LwIP debug logs + sl_enable_wifi_debug = false } if (chip_enable_wifi && !wifi_soc) { @@ -51,6 +54,12 @@ config("wifi-platform-config") { defines = [] include_dirs = [] + if (sl_enable_wifi_debug) { + defines += [ "WIFI_DEBUG_ENABLED=1" ] + } else { + defines += [ "WIFI_DEBUG_ENABLED=0" ] + } + if (use_rs9116) { # All the stuff from wiseconnect include_dirs += rs911x_inc_plat @@ -65,6 +74,7 @@ config("wifi-platform-config") { "SL_WIFI_SSID=\"${chip_default_wifi_ssid}\"", ] } + if (chip_default_wifi_psk != "") { assert(chip_default_wifi_ssid != "", "ssid can't be null if psk is provided") @@ -120,8 +130,6 @@ source_set("wifi-platform") { # All the stuff from wiseconnect sources += rs9117_src_sapi - - #add compilation flags for rs991x build. This will be addressed directly in wiseconnect sdk in the next version release of that sdk } else if (use_wf200) { sources += wf200_plat_src } @@ -142,6 +150,7 @@ source_set("wifi-platform") { if (use_wf200 || use_rs9116) { sources += [ "${silabs_platform_dir}/wifi/lwip-support/dhcp_client.cpp", + "${silabs_platform_dir}/wifi/lwip-support/dhcp_client.h", "${silabs_platform_dir}/wifi/lwip-support/ethernetif.cpp", "${silabs_platform_dir}/wifi/lwip-support/ethernetif.h", "${silabs_platform_dir}/wifi/lwip-support/lwip_netif.cpp", diff --git a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp index 0b4135a50a..514af648af 100644 --- a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp +++ b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp @@ -93,9 +93,6 @@ namespace { #if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE // TODO: should be removed once we are getting the press interrupt for button 0 with sleep bool btn0_pressed = false; -#ifdef ENABLE_CHIP_SHELL -bool ps_requirement_added = false; -#endif // ENABLE_CHIP_SHELL #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE bool hasNotifiedWifiConnectivity = false; @@ -550,37 +547,6 @@ int32_t sl_wifi_platform_disconnect(void) return sl_net_down((sl_net_interface_t) SL_NET_WIFI_CLIENT_INTERFACE); } -/****************************************************************** - * @fn wfx_rsi_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) - * @brief - * Setting the RS911x in DTIM sleep based mode - * - * @param[in] sl_si91x_ble_state : State to set for the BLE - * @param[in] sl_si91x_wifi_state : State to set for the WiFi - * @return - * None - *********************************************************************/ -int32_t wfx_rsi_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) -{ - int32_t status; - - status = rsi_bt_power_save_profile(sl_si91x_ble_state, 0); - if (status != RSI_SUCCESS) - { - ChipLogError(DeviceLayer, "rsi_bt_power_save_profile failed: 0x%lx", static_cast(status)); - return status; - } - sl_wifi_performance_profile_t wifi_profile = { .profile = sl_si91x_wifi_state }; - status = sl_wifi_set_performance_profile(&wifi_profile); - if (status != RSI_SUCCESS) - { - ChipLogError(DeviceLayer, "sl_wifi_set_performance_profile failed: 0x%lx", static_cast(status)); - return status; - } - - return status; -} - sl_status_t show_scan_results(sl_wifi_scan_result_t * scan_result) { SL_WIFI_ARGS_CHECK_NULL_POINTER(scan_result); @@ -897,9 +863,23 @@ void wfx_dhcp_got_ipv4(uint32_t ip) * @return SL_STATUS_OK if successful, * SL_STATUS_FAIL otherwise ***********************************************************************/ -sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, - sl_si91x_performance_profile_t sl_si91x_wifi_state) // TODO : Figure out why the extern C is necessary +sl_status_t wfx_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state) { - return (wfx_rsi_power_save(sl_si91x_ble_state, sl_si91x_wifi_state) ? SL_STATUS_FAIL : SL_STATUS_OK); + int32_t error = rsi_bt_power_save_profile(sl_si91x_ble_state, 0); + if (error != RSI_SUCCESS) + { + ChipLogError(DeviceLayer, "rsi_bt_power_save_profile failed: %ld", error); + return SL_STATUS_FAIL; + } + + sl_wifi_performance_profile_t wifi_profile = { .profile = sl_si91x_wifi_state }; + sl_status_t status = sl_wifi_set_performance_profile(&wifi_profile); + if (status != SL_STATUS_OK) + { + ChipLogError(DeviceLayer, "sl_wifi_set_performance_profile failed: 0x%lx", static_cast(status)); + return status; + } + + return SL_STATUS_OK; } #endif diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp index 430b9bbddb..698c839a10 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp @@ -41,7 +41,6 @@ namespace { constexpr uint8_t kWlanMinRetryIntervalsInSec = 1; constexpr uint8_t kWlanMaxRetryIntervalsInSec = 60; -constexpr uint8_t kWlanRetryIntervalInSec = 5; uint8_t retryInterval = kWlanMinRetryIntervalsInSec; osTimerId_t sRetryTimer; @@ -52,7 +51,7 @@ osTimerId_t sRetryTimer; void RetryConnectionTimerHandler(void * arg) { #if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE - wfx_rsi_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); + wfx_power_save(RSI_ACTIVE, HIGH_PERFORMANCE); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE if (wfx_connect_to_ap() != SL_STATUS_OK) { @@ -178,54 +177,23 @@ void wfx_ip_changed_notify(int got_ip) *************************************************************************************/ void wfx_retry_connection(uint16_t retryAttempt) { - // During commissioning, we retry to join the network MAX_JOIN_RETRIES_COUNT - if (/*BaseApplication::sAppDelegate.isCommissioningInProgress()*/ true) + if (retryInterval > kWlanMaxRetryIntervalsInSec) { - if (retryAttempt < MAX_JOIN_RETRIES_COUNT) - { - ChipLogProgress(DeviceLayer, "wfx_retry_connection : Next attempt after %d Seconds", kWlanRetryIntervalInSec); - if (osTimerStart(sRetryTimer, pdMS_TO_TICKS(CONVERT_SEC_TO_MS(kWlanRetryIntervalInSec))) != osOK) - { - ChipLogProgress(DeviceLayer, "Failed to start retry timer"); - // Sending the join command if retry timer failed to start - if (wfx_connect_to_ap() != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "wfx_connect_to_ap() failed."); - } - return; - } - } - else - { - ChipLogProgress(DeviceLayer, "Connect failed after max %d tries", retryAttempt); - } + retryInterval = kWlanMaxRetryIntervalsInSec; } - else + if (osTimerStart(sRetryTimer, pdMS_TO_TICKS(CONVERT_SEC_TO_MS(retryInterval))) != osOK) { - /* After disconnection or power cycle the DUT - * At the telescopic time interval device try to reconnect with AP, upto WLAN_MAX_RETRY_TIMER_MS intervals - * are telescopic. If interval exceed WLAN_MAX_RETRY_TIMER_MS then it will try to reconnect at - * WLAN_MAX_RETRY_TIMER_MS intervals. - */ - if (retryInterval > kWlanMaxRetryIntervalsInSec) - { - retryInterval = kWlanMaxRetryIntervalsInSec; - } - if (osTimerStart(sRetryTimer, pdMS_TO_TICKS(CONVERT_SEC_TO_MS(retryInterval))) != osOK) + ChipLogProgress(DeviceLayer, "Failed to start retry timer"); + // Sending the join command if retry timer failed to start + if (wfx_connect_to_ap() != SL_STATUS_OK) { - ChipLogProgress(DeviceLayer, "Failed to start retry timer"); - // Sending the join command if retry timer failed to start - if (wfx_connect_to_ap() != SL_STATUS_OK) - { - ChipLogError(DeviceLayer, "wfx_connect_to_ap() failed."); - } - return; + ChipLogError(DeviceLayer, "wfx_connect_to_ap() failed."); } -#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE - wfx_rsi_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); -#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE - ChipLogProgress(DeviceLayer, "wfx_retry_connection : Next attempt after %d Seconds", retryInterval); - retryInterval += retryInterval; return; } +#if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE + wfx_power_save(RSI_SLEEP_MODE_8, STANDBY_POWER_SAVE_WITH_RAM_RETENTION); +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE + ChipLogProgress(DeviceLayer, "wfx_retry_connection : Next attempt after %d Seconds", retryInterval); + retryInterval += retryInterval; } diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h index f6364d040e..012683aef6 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h @@ -63,11 +63,6 @@ #define GET_IPV6_FAIL (0) #define IP_STATUS_SUCCESS (1) -#define SL_WFX_STARTUP_IND_ID (1) -#define SL_WFX_CONNECT_IND_ID (2) -#define SL_WFX_DISCONNECT_IND_ID (3) -#define SL_WFX_SCAN_COMPLETE_ID (4) - // TASK and Interrupt Macros #define SUCCESS_STATUS (1) @@ -275,14 +270,6 @@ int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info); int32_t wfx_rsi_reset_count(); int32_t sl_wifi_platform_disconnect(); -#if CHIP_CONFIG_ENABLE_ICD_SERVER -#if SLI_SI917 -int32_t wfx_rsi_power_save(rsi_power_save_profile_mode_t sl_si91x_ble_state, sl_si91x_performance_profile_t sl_si91x_wifi_state); -#else -int32_t wfx_rsi_power_save(); -#endif /* SLI_SI917 */ -#endif /* SL_ICD_ENABLED */ - /** * @brief Posts an event to the Wi-Fi task * @@ -304,7 +291,6 @@ void sl_button_on_change(uint8_t btn, uint8_t btnAction); #ifdef WF200_WIFI void sl_wfx_host_gpio_init(void); void wfx_bus_start(void); -sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload); #endif /* WF200_WIFI */ #ifdef __cplusplus diff --git a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp index 7e880f62e9..c37d6ab933 100644 --- a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp +++ b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp @@ -140,7 +140,7 @@ static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len) if (!(ip6_addr_ispreferred(netif_ip6_addr_state(netif, 0))) && (memcmp(netif->hwaddr, src_mac, netif->hwaddr_len) == 0) && (memcmp(netif->hwaddr, dst_mac, netif->hwaddr_len) != 0)) { -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "lwip_input: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", @@ -163,7 +163,7 @@ static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len) memcpy((uint8_t *) q->payload, (uint8_t *) b + bufferoffset, q->len); bufferoffset += q->len; } -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "lwip_input: ACCEPT %ld, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", bufferoffset, @@ -255,7 +255,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) int i = 0; result = SL_STATUS_FAIL; -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "WF200: Out %d", (int) framelength); #endif @@ -302,7 +302,7 @@ void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer) len = rx_buffer->body.frame_length; buffer = (uint8_t *) &(rx_buffer->body.frame[rx_buffer->body.frame_padding]); -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "WF200: In %d", (int) len); #endif @@ -310,14 +310,14 @@ void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer) } else { -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "WF200: NO-INTF"); #endif } } else { -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "WF200: Invalid frame IN"); #endif } @@ -354,7 +354,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) struct pbuf * q; uint16_t framelength = 0; uint16_t datalength = 0; -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "LWIP : low_level_output"); #endif if (xSemaphoreTake(ethout_sem, portMAX_DELAY) != pdTRUE) @@ -370,7 +370,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) { framelength = LWIP_FRAME_ALIGNMENT; } -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "EN-RSI: Output"); #endif if ((netif->flags & (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) != (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) @@ -387,7 +387,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) return ERR_IF; } -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED uint8_t * b = (uint8_t *) p->payload; ChipLogProgress(DeviceLayer, "EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]); @@ -403,7 +403,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) /* Add junk data to the end for frame alignment if framelength is less than 60 */ wfx_rsi_pkt_add_data(packet, (uint8_t *) (p->payload), LWIP_FRAME_ALIGNMENT - datalength, datalength); } -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "EN-RSI: Sending %d", framelength); #endif @@ -417,7 +417,7 @@ static err_t low_level_output(struct netif * netif, struct pbuf * p) return ERR_IF; } -#ifdef WIFI_DEBUG_ENABLED +#if WIFI_DEBUG_ENABLED ChipLogProgress(DeviceLayer, "EN-RSI:Xmit %d", framelength); #endif xSemaphoreGive(ethout_sem); diff --git a/src/platform/silabs/wifi/rs911x/WifiInterface.cpp b/src/platform/silabs/wifi/rs911x/WifiInterface.cpp index c918b3af36..8b811534ca 100644 --- a/src/platform/silabs/wifi/rs911x/WifiInterface.cpp +++ b/src/platform/silabs/wifi/rs911x/WifiInterface.cpp @@ -234,39 +234,6 @@ int32_t sl_wifi_platform_disconnect(void) return rsi_wlan_disconnect(); } -#if SL_ICD_ENABLED -/****************************************************************** - * @fn wfx_rsi_power_save(void) - * @brief - * Setting the RS911x in DTIM sleep based mode - * - * @param[in] None - * @return - * None - *********************************************************************/ -int32_t wfx_rsi_power_save(void) -{ - int32_t status; -#ifdef RSI_BLE_ENABLE - status = rsi_bt_power_save_profile(RSI_SLEEP_MODE_2, RSI_MAX_PSP); - if (status != RSI_SUCCESS) - { - ChipLogError(DeviceLayer, "BT Powersave Config Failed, Error Code : 0x%lX", status); - return status; - } -#endif /* RSI_BLE_ENABLE */ - - status = rsi_wlan_power_save_profile(RSI_SLEEP_MODE_2, RSI_MAX_PSP); - if (status != RSI_SUCCESS) - { - ChipLogError(DeviceLayer, "Powersave Config Failed, Error Code : 0x%lX", status); - return status; - } - ChipLogDetail(DeviceLayer, "Powersave Config Success"); - return status; -} -#endif /* SL_ICD_ENABLED */ - /****************************************************************** * @fn wfx_rsi_join_cb(uint16_t status, const uint8_t *buf, const uint16_t len) * @brief @@ -964,8 +931,26 @@ int32_t wfx_rsi_send_data(void * p, uint16_t len) * @return SL_STATUS_OK if successful, * SL_STATUS_FAIL otherwise ***********************************************************************/ -sl_status_t wfx_power_save(void) // TODO : Figure out why the extern C is necessary +sl_status_t wfx_power_save(void) { - return (wfx_rsi_power_save() ? SL_STATUS_FAIL : SL_STATUS_OK); + int32_t status; +#ifdef RSI_BLE_ENABLE + status = rsi_bt_power_save_profile(RSI_SLEEP_MODE_2, RSI_MAX_PSP); + if (status != RSI_SUCCESS) + { + ChipLogError(DeviceLayer, "BT Powersave Config Failed, Error Code : 0x%lX", status); + return SL_STATUS_FAIL; + } +#endif /* RSI_BLE_ENABLE */ + + status = rsi_wlan_power_save_profile(RSI_SLEEP_MODE_2, RSI_MAX_PSP); + if (status != RSI_SUCCESS) + { + ChipLogError(DeviceLayer, "Powersave Config Failed, Error Code : 0x%lX", status); + return SL_STATUS_FAIL; + } + + ChipLogDetail(DeviceLayer, "Powersave Config Success"); + return SL_STATUS_OK; } #endif /* SL_ICD_ENABLED */ diff --git a/src/platform/silabs/wifi/wf200/WifiInterface.cpp b/src/platform/silabs/wifi/wf200/WifiInterface.cpp index fef3cb3a63..ebeaa2d4a4 100644 --- a/src/platform/silabs/wifi/wf200/WifiInterface.cpp +++ b/src/platform/silabs/wifi/wf200/WifiInterface.cpp @@ -26,6 +26,7 @@ #include "sl_wfx_cmd_api.h" #include "sl_wfx_constants.h" #include "task.h" +#include #include #include #include @@ -224,16 +225,6 @@ typedef struct __attribute__((__packed__)) sl_wfx_mib_req_s sl_wfx_get_counters_cnf_t * counters; -/**************************************************************************** - * @brief - * get the wifi state - * @return returns wificonetext state - *****************************************************************************/ -sl_wfx_state_t wfx_get_wifi_state(void) -{ - return wifiContext.state; -} - sl_status_t get_all_counters(void) { sl_status_t result; @@ -328,7 +319,7 @@ static void wfx_events_task_start(void) * @returns Returns SL_STATUS_OK if successful, *SL_STATUS_FAIL otherwise *****************************************************************************/ -sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload) +extern "C" sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload) { switch (event_payload->header.id) { @@ -739,14 +730,14 @@ static void wfx_events_task(void * p_arg) retryJoin = 0; wfx_lwip_set_sta_link_up(); #if CHIP_CONFIG_ENABLE_ICD_SERVER - if (!(wfx_get_wifi_state() & SL_WFX_AP_INTERFACE_UP)) + if (!(wifiContext.state & SL_WFX_AP_INTERFACE_UP)) { // Enable the power save ChipLogProgress(DeviceLayer, "WF200 going to DTIM based sleep"); sl_wfx_set_power_mode(WFM_PM_MODE_DTIM, WFM_PM_POLL_FAST_PS, BEACON_1, 0 /*timeout*/); sl_wfx_enable_device_power_save(); } -#endif /* CHIP_CONFIG_ENABLE_ICD_SERVER */ +#endif // CHIP_CONFIG_ENABLE_ICD_SERVER } if (flags & SL_WFX_DISCONNECT) diff --git a/src/platform/silabs/wifi/wf200/platform/efr_spi.c b/src/platform/silabs/wifi/wf200/platform/efr_spi.c index 6f80fc83d9..434253f855 100644 --- a/src/platform/silabs/wifi/wf200/platform/efr_spi.c +++ b/src/platform/silabs/wifi/wf200/platform/efr_spi.c @@ -437,8 +437,6 @@ sl_status_t sl_wfx_host_post_lcd_spi_transfer(void) #endif // SL_SPICTRL_MUX return SL_STATUS_OK; } -#else -#error still not working #endif // SL_LCDCTRL_MUX #if SL_UARTCTRL_MUX diff --git a/src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h b/src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h index dc9bcd2852..d33b5fb680 100644 --- a/src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h +++ b/src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h @@ -15,6 +15,8 @@ * limitations under the License. */ +// TODO: Should use the file from simplicity sdk + #pragma once #include "FreeRTOS.h" @@ -26,6 +28,7 @@ #ifdef __cplusplus extern "C" { #endif +sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload); uint8_t sl_wfx_host_get_waited_event(void); sl_status_t wfx_soft_init(void); diff --git a/src/platform/silabs/wifi/wf200/platform/wf200_init.c b/src/platform/silabs/wifi/wf200/platform/wf200_init.c index 40f1aaf08a..92663f9b05 100644 --- a/src/platform/silabs/wifi/wf200/platform/wf200_init.c +++ b/src/platform/silabs/wifi/wf200/platform/wf200_init.c @@ -319,6 +319,7 @@ sl_status_t sl_wfx_host_reset_chip(void) *****************************************************************************/ sl_status_t sl_wfx_host_wait_for_wake_up(void) { + xSemaphoreTake(wfx_wakeup_sem, pdMS_TO_TICKS(0)); xSemaphoreTake(wfx_wakeup_sem, pdMS_TO_TICKS(3)); return SL_STATUS_OK; diff --git a/src/platform/silabs/wifi/wf200/wf200.gni b/src/platform/silabs/wifi/wf200/wf200.gni index 437f9def5d..c8e1308f5f 100644 --- a/src/platform/silabs/wifi/wf200/wf200.gni +++ b/src/platform/silabs/wifi/wf200/wf200.gni @@ -26,5 +26,4 @@ wf200_plat_src = [ "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_wfx_task.h", "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_custom_board.h", "${chip_root}/src/platform/silabs/wifi/wf200/platform/spi_multiplex.h", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_wfx_board.h", ] diff --git a/src/platform/silabs/wifi/wfx_msgs.h b/src/platform/silabs/wifi/wfx_msgs.h index af167a1f2c..ec1744c998 100644 --- a/src/platform/silabs/wifi/wfx_msgs.h +++ b/src/platform/silabs/wifi/wfx_msgs.h @@ -26,6 +26,15 @@ #include "sl_wfx_api.h" #include "sl_wfx_constants.h" #else + +// These names exists in the Si SDK as typedef enum. If they are present in the WF200 builds, we end up with conflicting +// definitions but no erros because one is a define the other is a typedef enum. This causes different files to use different +// values. +#define SL_WFX_STARTUP_IND_ID (1) +#define SL_WFX_CONNECT_IND_ID (2) +#define SL_WFX_DISCONNECT_IND_ID (3) +#define SL_WFX_SCAN_COMPLETE_ID (4) + typedef struct { uint8_t octet[6]; ///< Table to store a MAC address diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 9ca85baa47..40296046cc 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -53,8 +53,8 @@ declare_args() { sl_matter_ble_extended_adv = false # ICD Openthread Configuration flags - sl_ot_idle_interval_ms = 15000 # 15s Idle Intervals - sl_ot_active_interval_ms = 200 # 200ms Active Intervals + sl_transport_idle_interval_ms = 15000 # 15s Idle Intervals + sl_transport_active_interval_ms = 200 # 200ms Active Intervals # SSED Specific configurations sl_ot_csl_timeout_sec = 30 # 30s CSL timeout @@ -630,15 +630,12 @@ template("efr32_sdk") { "SL_ACTIVE_MODE_DURATION_MS=${sl_active_mode_duration_ms}", "SL_IDLE_MODE_DURATION_S=${sl_idle_mode_duration_s}", "SL_ICD_SUPPORTED_CLIENTS_PER_FABRIC=${sl_icd_supported_clients_per_fabric}", + "SL_TRANSPORT_IDLE_INTERVAL=${sl_transport_idle_interval_ms}", + "SL_TRANSPORT_ACTIVE_INTERVAL=${sl_transport_active_interval_ms}", ] if (defined(invoker.chip_enable_openthread) && invoker.chip_enable_openthread) { - defines += [ - "SL_OT_IDLE_INTERVAL=${sl_ot_idle_interval_ms}", - "SL_OT_ACTIVE_INTERVAL=${sl_ot_active_interval_ms}", - ] - if (enable_synchronized_sed) { defines += [ "CHIP_DEVICE_CONFIG_THREAD_SSED=1", @@ -646,18 +643,6 @@ template("efr32_sdk") { ] } } - - if (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) { - defines += [ - # Used for wifi devices to get packet details - # TODO: Remove this flag, once the communication is fixed - "WIFI_DEBUG_ENABLED=1", - ] - - # This is kept due to the warning on the LWIP when on demand timer is added - # TODO: remove this flag once the warning is fixed in SiSDK MATTER-3946 - cflags_c = [ "-Wno-implicit-function-declaration" ] - } } if (chip_build_libshell) { # matter shell @@ -1025,7 +1010,6 @@ template("efr32_sdk") { sources += [ "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus/sl_wfx_bus.c", "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus/sl_wfx_bus_spi.c", - "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/secure_link/sl_wfx_secure_link.c", "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/sl_wfx.c", ] } From 70f2f3e028bcf21d273c40dc217d6d8fef3b5fc5 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Thu, 28 Nov 2024 07:02:14 -0500 Subject: [PATCH 106/219] [Silabs] Move Wi-Fi interface files to the final structure (#36644) * Move files * Move wifi files to their final location & cleanup * Restyled by clang-format * rename directories * rename paths for new locations * Restyled by clang-format * update include path with the structure --------- Co-authored-by: Restyled.io --- examples/platform/silabs/display/demo-ui.c | 2 +- .../silabs/efr32/OTAImageProcessorImpl.cpp | 2 +- src/platform/silabs/wifi/BUILD.gn | 2 +- .../silabs/wifi/SiWx/WifiInterface.cpp | 2 +- .../platform => SiWx/ncp}/efx32_ncp_host.c | 4 +-- .../wifi/{rs911x => SiWx/ncp}/rs9117.gni | 11 +++----- .../ncp/sl_board_configuration.h} | 17 ++++++++++++ .../ncp}/sl_si91x_ncp_utility.c | 3 --- .../ncp}/sl_si91x_ncp_utility.h | 19 ++++---------- .../{wf200/platform => ncp}/spi_multiplex.h | 0 .../wifi/rs911x/{platform => ncp}/efx_spi.c | 2 +- .../rsi_board_configuration.h | 0 .../wifi/rs911x/{platform => ncp}/rsi_hal.h | 0 .../{platform => ncp}/rsi_hal_mcu_interrupt.c | 26 +++++-------------- .../{platform => ncp}/rsi_hal_mcu_ioports.c | 16 +++++------- .../{platform => ncp}/rsi_hal_mcu_rtc.c | 0 .../{platform => ncp}/rsi_hal_mcu_timer.c | 0 .../wifi/rs911x/{ => ncp}/rsi_wlan_config.h | 11 +------- .../sl_board_configuration.h | 0 src/platform/silabs/wifi/rs911x/rs911x.gni | 12 ++++----- .../silabs/wifi/wf200/WifiInterface.cpp | 6 ++--- .../wifi/wf200/{platform => ncp}/efr_spi.c | 2 +- .../wf200/{platform => ncp}/sl_custom_board.h | 0 .../wf200/{platform => ncp}/sl_wfx_board.h | 0 .../wf200/{platform => ncp}/sl_wfx_host.h | 0 .../wf200/{platform => ncp}/sl_wfx_task.c | 0 .../wf200/{platform => ncp}/sl_wfx_task.h | 0 .../wifi/wf200/{platform => ncp}/wf200_init.c | 0 src/platform/silabs/wifi/wf200/wf200.gni | 16 ++++++------ third_party/silabs/efr32_sdk.gni | 5 +--- 30 files changed, 67 insertions(+), 91 deletions(-) rename src/platform/silabs/wifi/{rs911x/platform => SiWx/ncp}/efx32_ncp_host.c (96%) rename src/platform/silabs/wifi/{rs911x => SiWx/ncp}/rs9117.gni (86%) rename src/platform/silabs/wifi/{rs911x/platform/sl_board_configuration_SiWx917.h => SiWx/ncp/sl_board_configuration.h} (74%) rename src/platform/silabs/wifi/{rs911x/platform => SiWx/ncp}/sl_si91x_ncp_utility.c (96%) rename src/platform/silabs/wifi/{rs911x/platform => SiWx/ncp}/sl_si91x_ncp_utility.h (75%) rename src/platform/silabs/wifi/{wf200/platform => ncp}/spi_multiplex.h (100%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/efx_spi.c (99%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/rsi_board_configuration.h (100%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/rsi_hal.h (100%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/rsi_hal_mcu_interrupt.c (95%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/rsi_hal_mcu_ioports.c (99%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/rsi_hal_mcu_rtc.c (100%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/rsi_hal_mcu_timer.c (100%) rename src/platform/silabs/wifi/rs911x/{ => ncp}/rsi_wlan_config.h (97%) rename src/platform/silabs/wifi/rs911x/{platform => ncp}/sl_board_configuration.h (100%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/efr_spi.c (99%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/sl_custom_board.h (100%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/sl_wfx_board.h (100%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/sl_wfx_host.h (100%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/sl_wfx_task.c (100%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/sl_wfx_task.h (100%) rename src/platform/silabs/wifi/wf200/{platform => ncp}/wf200_init.c (100%) diff --git a/examples/platform/silabs/display/demo-ui.c b/examples/platform/silabs/display/demo-ui.c index fb41a5b309..fac00dc0d8 100644 --- a/examples/platform/silabs/display/demo-ui.c +++ b/examples/platform/silabs/display/demo-ui.c @@ -27,7 +27,7 @@ #include "sl_memlcd.h" #include #if SL_WIFI && !SLI_SI91X_MCU_INTERFACE -#include +#include #endif // SL_WIFI && !SLI_SI91X_MCU_INTERFACE #include diff --git a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp index a884071560..09d37d0ca7 100644 --- a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp @@ -22,7 +22,7 @@ #include #if SL_WIFI -#include +#include #endif // SL_WIFI extern "C" { diff --git a/src/platform/silabs/wifi/BUILD.gn b/src/platform/silabs/wifi/BUILD.gn index db58633599..304fa89cd2 100644 --- a/src/platform/silabs/wifi/BUILD.gn +++ b/src/platform/silabs/wifi/BUILD.gn @@ -43,7 +43,7 @@ if (chip_enable_wifi && !wifi_soc) { if (use_rs9116) { import("${silabs_platform_dir}/wifi/rs911x/rs911x.gni") } else if (use_SiWx917) { - import("${silabs_platform_dir}/wifi/rs911x/rs9117.gni") + import("${silabs_platform_dir}/wifi/SiWx/ncp/rs9117.gni") } if (use_wf200) { import("${silabs_platform_dir}/wifi/wf200/wf200.gni") diff --git a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp index 514af648af..291c9988d8 100644 --- a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp +++ b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp @@ -67,7 +67,7 @@ extern "C" { #if (EXP_BOARD) #include "rsi_bt_common_apis.h" -#include +#include #endif #if CHIP_CONFIG_ENABLE_ICD_SERVER && SLI_SI91X_MCU_INTERFACE diff --git a/src/platform/silabs/wifi/rs911x/platform/efx32_ncp_host.c b/src/platform/silabs/wifi/SiWx/ncp/efx32_ncp_host.c similarity index 96% rename from src/platform/silabs/wifi/rs911x/platform/efx32_ncp_host.c rename to src/platform/silabs/wifi/SiWx/ncp/efx32_ncp_host.c index c7173763d5..8991ffa8e6 100644 --- a/src/platform/silabs/wifi/rs911x/platform/efx32_ncp_host.c +++ b/src/platform/silabs/wifi/SiWx/ncp/efx32_ncp_host.c @@ -22,7 +22,6 @@ #include "em_gpio.h" #include "em_usart.h" #include "gpiointerrupt.h" -#include "sl_board_configuration_SiWx917.h" #include "sl_constants.h" #include "sl_rsi_utility.h" #include "sl_si91x_host_interface.h" @@ -30,7 +29,8 @@ #include "sl_si91x_status.h" #include "sl_status.h" #include "sl_wifi_constants.h" -#include +#include +#include #include #include diff --git a/src/platform/silabs/wifi/rs911x/rs9117.gni b/src/platform/silabs/wifi/SiWx/ncp/rs9117.gni similarity index 86% rename from src/platform/silabs/wifi/rs911x/rs9117.gni rename to src/platform/silabs/wifi/SiWx/ncp/rs9117.gni index cbeaf98698..6be9a7337a 100644 --- a/src/platform/silabs/wifi/rs911x/rs9117.gni +++ b/src/platform/silabs/wifi/SiWx/ncp/rs9117.gni @@ -18,17 +18,14 @@ import("${silabs_sdk_build_root}/efr32_sdk.gni") rs911x_src_plat = [ "${chip_root}/src/platform/silabs/wifi/SiWx/WifiInterface.cpp", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_interrupt.c", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.c", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/sl_board_configuration.h", + "${chip_root}/src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.c", + "${chip_root}/src/platform/silabs/wifi/SiWx/ncp/sl_board_configuration.h", "${chip_root}/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp", "${chip_root}/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h", - - # TODO: We shouldn't need a file form the WF200 for the SiWx917 NCP builds - "${chip_root}/src/platform/silabs/wifi/wf200/platform/spi_multiplex.h", + "${chip_root}/src/platform/silabs/wifi/ncp/spi_multiplex.h", # TODO : We should be using the file from the Wiseconnect SDK and not our copy of it. - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/efx32_ncp_host.c", + "${chip_root}/src/platform/silabs/wifi/SiWx/ncp/efx32_ncp_host.c", ] rs9117_inc_plat = [ "${wifi_sdk_root}/components/si91x/ble/inc" ] diff --git a/src/platform/silabs/wifi/rs911x/platform/sl_board_configuration_SiWx917.h b/src/platform/silabs/wifi/SiWx/ncp/sl_board_configuration.h similarity index 74% rename from src/platform/silabs/wifi/rs911x/platform/sl_board_configuration_SiWx917.h rename to src/platform/silabs/wifi/SiWx/ncp/sl_board_configuration.h index 7145e318b3..0aad8bd4e8 100644 --- a/src/platform/silabs/wifi/rs911x/platform/sl_board_configuration_SiWx917.h +++ b/src/platform/silabs/wifi/SiWx/ncp/sl_board_configuration.h @@ -1,3 +1,20 @@ +/* + * + * Copyright (c) 2024 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. + */ + #pragma once #ifdef SL_UART diff --git a/src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.c b/src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.c similarity index 96% rename from src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.c rename to src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.c index 1d1ab1409c..50b8ffdba0 100644 --- a/src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.c +++ b/src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.c @@ -15,9 +15,6 @@ * limitations under the License. */ -/** - * Includes - */ #include #include #include diff --git a/src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.h b/src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.h similarity index 75% rename from src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.h rename to src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.h index b434e35f82..437be2dcb0 100644 --- a/src/platform/silabs/wifi/rs911x/platform/sl_si91x_ncp_utility.h +++ b/src/platform/silabs/wifi/SiWx/ncp/sl_si91x_ncp_utility.h @@ -21,24 +21,16 @@ * devices such as External Flash and LCD. * That can be extended to other families as well. */ -#ifndef SL_SI91X_NCP_UTILITY_H -#define SL_SI91X_NCP_UTILITY_H - #pragma once + #include "FreeRTOS.h" +#include "em_usart.h" #include "semphr.h" #include "silabs_utils.h" -#include "sl_status.h" - -// TODO: This is a WF200 specific include. It is not clear why we need this in the 917 NCP files. -#include - -#if defined(CHIP_9117) -#include "em_usart.h" -#include "sl_board_configuration_SiWx917.h" #include "sl_spidrv_exp_config.h" - -#endif // CHIP_9117 +#include "sl_status.h" +#include +#include #define USART_INITSYNC_BAUDRATE 12500000 @@ -48,4 +40,3 @@ sl_status_t spi_board_init(void); extern uint32_t rx_ldma_channel; extern uint32_t tx_ldma_channel; -#endif // SL_SI91X_NCP_UTILITY_H diff --git a/src/platform/silabs/wifi/wf200/platform/spi_multiplex.h b/src/platform/silabs/wifi/ncp/spi_multiplex.h similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/spi_multiplex.h rename to src/platform/silabs/wifi/ncp/spi_multiplex.h diff --git a/src/platform/silabs/wifi/rs911x/platform/efx_spi.c b/src/platform/silabs/wifi/rs911x/ncp/efx_spi.c similarity index 99% rename from src/platform/silabs/wifi/rs911x/platform/efx_spi.c rename to src/platform/silabs/wifi/rs911x/ncp/efx_spi.c index a339f711a4..2467bd311d 100644 --- a/src/platform/silabs/wifi/rs911x/platform/efx_spi.c +++ b/src/platform/silabs/wifi/rs911x/ncp/efx_spi.c @@ -34,7 +34,7 @@ #include "sl_status.h" #include "spidrv.h" #include "task.h" -#include +#include #ifdef SL_BOARD_NAME #include "sl_board_control.h" diff --git a/src/platform/silabs/wifi/rs911x/platform/rsi_board_configuration.h b/src/platform/silabs/wifi/rs911x/ncp/rsi_board_configuration.h similarity index 100% rename from src/platform/silabs/wifi/rs911x/platform/rsi_board_configuration.h rename to src/platform/silabs/wifi/rs911x/ncp/rsi_board_configuration.h diff --git a/src/platform/silabs/wifi/rs911x/platform/rsi_hal.h b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal.h similarity index 100% rename from src/platform/silabs/wifi/rs911x/platform/rsi_hal.h rename to src/platform/silabs/wifi/rs911x/ncp/rsi_hal.h diff --git a/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_interrupt.c b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_interrupt.c similarity index 95% rename from src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_interrupt.c rename to src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_interrupt.c index 8bd277e624..d1d1bd2aae 100644 --- a/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_interrupt.c +++ b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_interrupt.c @@ -15,10 +15,7 @@ * limitations under the License. */ -#include -#include -#include - +#include "FreeRTOS.h" #include "dmadrv.h" #include "em_chip.h" #include "em_cmu.h" @@ -27,25 +24,16 @@ #include "em_gpio.h" #include "em_ldma.h" #include "em_usart.h" +#include "event_groups.h" #include "gpiointerrupt.h" +#include "rsi_board_configuration.h" +#include "rsi_driver.h" #include "sl_device_init_clocks.h" #include "sl_status.h" - -#include "FreeRTOS.h" -#include "event_groups.h" #include "task.h" - -#if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) -#include "sl_board_configuration.h" - -#include "sl_rsi_utility.h" -#include "sl_si91x_host_interface.h" - -void gpio_interrupt(uint8_t interrupt_number); -#else -#include "rsi_board_configuration.h" -#include "rsi_driver.h" -#endif +#include +#include +#include typedef void (*UserIntCallBack_t)(void); UserIntCallBack_t call_back, gpio_callback; diff --git a/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_ioports.c b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_ioports.c similarity index 99% rename from src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_ioports.c rename to src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_ioports.c index ba517b417b..5e4089d127 100644 --- a/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_ioports.c +++ b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_ioports.c @@ -15,10 +15,7 @@ * limitations under the License. */ -#include -#include -#include - +#include "FreeRTOS.h" #include "dmadrv.h" #include "em_chip.h" #include "em_cmu.h" @@ -27,16 +24,17 @@ #include "em_gpio.h" #include "em_ldma.h" #include "em_usart.h" +#include "event_groups.h" #include "gpiointerrupt.h" +#include "rsi_board_configuration.h" +#include "rsi_driver.h" #include "sl_device_init_clocks.h" #include "sl_status.h" - -#include "FreeRTOS.h" -#include "event_groups.h" #include "task.h" +#include +#include +#include -#include "rsi_board_configuration.h" -#include "rsi_driver.h" /*===========================================================*/ /** * @fn void rsi_hal_config_gpio(uint8_t gpio_number,uint8_t mode,uint8_t value) diff --git a/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_rtc.c b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_rtc.c similarity index 100% rename from src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_rtc.c rename to src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_rtc.c diff --git a/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_timer.c b/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_timer.c similarity index 100% rename from src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_timer.c rename to src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_timer.c diff --git a/src/platform/silabs/wifi/rs911x/rsi_wlan_config.h b/src/platform/silabs/wifi/rs911x/ncp/rsi_wlan_config.h similarity index 97% rename from src/platform/silabs/wifi/rs911x/rsi_wlan_config.h rename to src/platform/silabs/wifi/rs911x/ncp/rsi_wlan_config.h index b851cd7958..6e14347fac 100644 --- a/src/platform/silabs/wifi/rs911x/rsi_wlan_config.h +++ b/src/platform/silabs/wifi/rs911x/ncp/rsi_wlan_config.h @@ -46,18 +46,9 @@ //! To set Extended custom feature select bit map #if WIFI_ENABLE_SECURITY_WPA3_TRANSITION -#ifdef CHIP_9117 -#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP \ - (EXT_FEAT_448K_M4SS_256K | EXT_FEAT_LOW_POWER_MODE | EXT_FEAT_XTAL_CLK_ENABLE | EXT_FEAT_IEEE_80211W) -#else /* !CHIP_9117 */ #define RSI_EXT_CUSTOM_FEATURE_BIT_MAP (EXT_FEAT_384K_MODE | EXT_FEAT_IEEE_80211W) -#endif /* CHIP_9117 */ -#else /* !WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ -#ifdef CHIP_9117 -#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP (EXT_FEAT_448K_M4SS_256K | EXT_FEAT_LOW_POWER_MODE | EXT_FEAT_XTAL_CLK_ENABLE) -#else /* !CHIP_9117 */ +#else /* !WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ #define RSI_EXT_CUSTOM_FEATURE_BIT_MAP EXT_FEAT_384K_MODE -#endif /* CHIP_9117 */ #endif /* WIFI_ENABLE_SECURITY_WPA3_TRANSITION */ //! To set Extended TCPIP feature select bit map diff --git a/src/platform/silabs/wifi/rs911x/platform/sl_board_configuration.h b/src/platform/silabs/wifi/rs911x/ncp/sl_board_configuration.h similarity index 100% rename from src/platform/silabs/wifi/rs911x/platform/sl_board_configuration.h rename to src/platform/silabs/wifi/rs911x/ncp/sl_board_configuration.h diff --git a/src/platform/silabs/wifi/rs911x/rs911x.gni b/src/platform/silabs/wifi/rs911x/rs911x.gni index 3daba8b049..54a53fb7da 100644 --- a/src/platform/silabs/wifi/rs911x/rs911x.gni +++ b/src/platform/silabs/wifi/rs911x/rs911x.gni @@ -18,12 +18,12 @@ import("${silabs_sdk_build_root}/efr32_sdk.gni") rs911x_src_plat = [ "${chip_root}/src/platform/silabs/wifi/rs911x/WifiInterface.cpp", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_interrupt.c", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_ioports.c", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/rsi_hal_mcu_timer.c", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/efx_spi.c", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/rsi_board_configuration.h", - "${chip_root}/src/platform/silabs/wifi/rs911x/platform/rsi_hal.h", + "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_interrupt.c", + "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_ioports.c", + "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal_mcu_timer.c", + "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/efx_spi.c", + "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_board_configuration.h", + "${chip_root}/src/platform/silabs/wifi/rs911x/ncp/rsi_hal.h", "${chip_root}/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp", ] diff --git a/src/platform/silabs/wifi/wf200/WifiInterface.cpp b/src/platform/silabs/wifi/wf200/WifiInterface.cpp index ebeaa2d4a4..1ff37ab617 100644 --- a/src/platform/silabs/wifi/wf200/WifiInterface.cpp +++ b/src/platform/silabs/wifi/wf200/WifiInterface.cpp @@ -33,9 +33,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/src/platform/silabs/wifi/wf200/platform/efr_spi.c b/src/platform/silabs/wifi/wf200/ncp/efr_spi.c similarity index 99% rename from src/platform/silabs/wifi/wf200/platform/efr_spi.c rename to src/platform/silabs/wifi/wf200/ncp/efr_spi.c index 434253f855..55f781d960 100644 --- a/src/platform/silabs/wifi/wf200/platform/efr_spi.c +++ b/src/platform/silabs/wifi/wf200/ncp/efr_spi.c @@ -32,7 +32,7 @@ #include "sl_wfx_host_api.h" #include "sl_wfx_task.h" #include "spidrv.h" -#include +#include #include #include #include diff --git a/src/platform/silabs/wifi/wf200/platform/sl_custom_board.h b/src/platform/silabs/wifi/wf200/ncp/sl_custom_board.h similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/sl_custom_board.h rename to src/platform/silabs/wifi/wf200/ncp/sl_custom_board.h diff --git a/src/platform/silabs/wifi/wf200/platform/sl_wfx_board.h b/src/platform/silabs/wifi/wf200/ncp/sl_wfx_board.h similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/sl_wfx_board.h rename to src/platform/silabs/wifi/wf200/ncp/sl_wfx_board.h diff --git a/src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h b/src/platform/silabs/wifi/wf200/ncp/sl_wfx_host.h similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h rename to src/platform/silabs/wifi/wf200/ncp/sl_wfx_host.h diff --git a/src/platform/silabs/wifi/wf200/platform/sl_wfx_task.c b/src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.c similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/sl_wfx_task.c rename to src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.c diff --git a/src/platform/silabs/wifi/wf200/platform/sl_wfx_task.h b/src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.h similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/sl_wfx_task.h rename to src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.h diff --git a/src/platform/silabs/wifi/wf200/platform/wf200_init.c b/src/platform/silabs/wifi/wf200/ncp/wf200_init.c similarity index 100% rename from src/platform/silabs/wifi/wf200/platform/wf200_init.c rename to src/platform/silabs/wifi/wf200/ncp/wf200_init.c diff --git a/src/platform/silabs/wifi/wf200/wf200.gni b/src/platform/silabs/wifi/wf200/wf200.gni index c8e1308f5f..0d166b1db4 100644 --- a/src/platform/silabs/wifi/wf200/wf200.gni +++ b/src/platform/silabs/wifi/wf200/wf200.gni @@ -18,12 +18,12 @@ import("${silabs_sdk_build_root}/efr32_sdk.gni") wf200_plat_src = [ "${chip_root}/src/platform/silabs/wifi/wf200/WifiInterface.cpp", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_wfx_task.c", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/wf200_init.c", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/efr_spi.c", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_wfx_board.h", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_wfx_host.h", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_wfx_task.h", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/sl_custom_board.h", - "${chip_root}/src/platform/silabs/wifi/wf200/platform/spi_multiplex.h", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.c", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/wf200_init.c", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/efr_spi.c", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/sl_wfx_board.h", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/sl_wfx_host.h", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/sl_wfx_task.h", + "${chip_root}/src/platform/silabs/wifi/wf200/ncp/sl_custom_board.h", + "${chip_root}/src/platform/silabs/wifi/ncp/spi_multiplex.h", ] diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 40296046cc..7861e827d7 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -370,10 +370,7 @@ template("efr32_sdk") { if (use_rs9116) { # TODO: we should create a seperate directory for headers that are necessary for the underlying sdks - _include_dirs += [ - "${chip_root}/src/platform/silabs/wifi/rs911x/platform", - "${chip_root}/src/platform/silabs/wifi/rs911x", - ] + _include_dirs += [ "${chip_root}/src/platform/silabs/wifi/rs911x/ncp" ] } if (use_rs9116 || use_SiWx917) { From 7805664ee3705ec8abe076eebe49450ae0ccf19d Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Thu, 28 Nov 2024 13:03:32 +0100 Subject: [PATCH 107/219] Deliver SIGINT to the shell thread to interrupt read() (#36533) * Deliver SIGINT to the sell thread to interrupt read() * Verify that TV apps exit cleanly * TV casting app with proper shutdown on SIGTERM * Fix import * Revert sigaction() usage, as it seems not to work on Darwin * Remove ifdefs * Use signal() instead of sigaction() on Darwin * Restyled by clang-format --------- Co-authored-by: Restyled.io --- examples/platform/linux/AppMain.cpp | 48 ++++++++++++---- examples/tv-casting-app/linux/main.cpp | 59 +++++++++++++++++++- examples/tv-casting-app/linux/simple-app.cpp | 57 ++++++++++++++++++- scripts/tests/run_tv_casting_test.py | 17 +----- src/lib/shell/Engine.h | 8 +++ src/lib/shell/MainLoopAmeba.cpp | 2 +- src/lib/shell/MainLoopDefault.cpp | 21 +++++-- src/lib/shell/MainLoopESP32.cpp | 2 +- src/lib/shell/MainLoopMW320.cpp | 2 +- src/lib/shell/MainLoopSilabs.cpp | 2 +- 10 files changed, 178 insertions(+), 40 deletions(-) diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 65763dc12d..b9c0cdf771 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -305,7 +305,7 @@ void StopMainEventLoop() else { Server::GetInstance().GenerateShutDownEvent(); - PlatformMgr().ScheduleWork([](intptr_t) { PlatformMgr().StopEventLoopTask(); }); + SystemLayer().ScheduleLambda([]() { PlatformMgr().StopEventLoopTask(); }); } } @@ -318,18 +318,13 @@ void Cleanup() // TODO(16968): Lifecycle management of storage-using components like GroupDataProvider, etc } -// TODO(#20664) REPL test will fail if signal SIGINT is not caught, temporarily keep following logic. - -// when the shell is enabled, don't intercept signals since it prevents the user from -// using expected commands like CTRL-C to quit the application. (see issue #17845) -// We should stop using signals for those faults, and move to a different notification -// means, like a pipe. (see issue #19114) -#if !defined(ENABLE_CHIP_SHELL) void StopSignalHandler(int /* signal */) { +#if defined(ENABLE_CHIP_SHELL) + Engine::Root().StopMainLoop(); +#endif StopMainEventLoop(); } -#endif // !defined(ENABLE_CHIP_SHELL) } // namespace @@ -409,6 +404,18 @@ int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions, SuccessOrExit(err); #endif +#if defined(ENABLE_CHIP_SHELL) + /* Block SIGINT and SIGTERM. Other threads created by the main thread + * will inherit the signal mask. Then we can explicitly unblock signals + * in the shell thread to handle them, so the read(stdin) call can be + * interrupted by a signal. */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + pthread_sigmask(SIG_BLOCK, &set, nullptr); +#endif + err = DeviceLayer::PlatformMgr().InitChipStack(); SuccessOrExit(err); @@ -531,11 +538,18 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); + Shell::RegisterCommissioneeCommands(); std::thread shellThread([]() { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + // Unblock SIGINT and SIGTERM, so that the shell thread can handle + // them - we need read() call to be interrupted. + pthread_sigmask(SIG_UNBLOCK, &set, nullptr); Engine::Root().RunMainLoop(); StopMainEventLoop(); }); - Shell::RegisterCommissioneeCommands(); #endif initParams.operationalServicePort = CHIP_PORT; initParams.userDirectedCommissioningPort = CHIP_UDC_PORT; @@ -670,12 +684,22 @@ void ChipLinuxAppMainLoop(AppMainLoopImplementation * impl) ApplicationInit(); -#if !defined(ENABLE_CHIP_SHELL) + // NOTE: For some reason, on Darwin, the signal handler is not called if the signal is + // registered with sigaction() call and TSAN is enabled. The problem seems to be + // related with the dispatch_semaphore_wait() function in the RunEventLoop() method. + // If this call is commented out, the signal handler is called as expected... +#if defined(__APPLE__) // NOLINTBEGIN(bugprone-signal-handler) signal(SIGINT, StopSignalHandler); signal(SIGTERM, StopSignalHandler); // NOLINTEND(bugprone-signal-handler) -#endif // !defined(ENABLE_CHIP_SHELL) +#else + struct sigaction sa = {}; + sa.sa_handler = StopSignalHandler; + sa.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sa, nullptr); + sigaction(SIGTERM, &sa, nullptr); +#endif if (impl != nullptr) { diff --git a/examples/tv-casting-app/linux/main.cpp b/examples/tv-casting-app/linux/main.cpp index 3a41f15d53..11e1c56e9f 100644 --- a/examples/tv-casting-app/linux/main.cpp +++ b/examples/tv-casting-app/linux/main.cpp @@ -16,6 +16,8 @@ * limitations under the License. */ +#include + #include "commands/clusters/SubscriptionsCommands.h" #include "commands/common/Commands.h" #include "commands/example/ExampleCredentialIssuerCommands.h" @@ -105,17 +107,56 @@ CHIP_ERROR ProcessClusterCommand(int argc, char ** argv) return CHIP_NO_ERROR; } +void StopMainEventLoop() +{ + Server::GetInstance().GenerateShutDownEvent(); + DeviceLayer::SystemLayer().ScheduleLambda([]() { DeviceLayer::PlatformMgr().StopEventLoopTask(); }); +} + +void StopSignalHandler(int /* signal */) +{ +#if defined(ENABLE_CHIP_SHELL) + Engine::Root().StopMainLoop(); +#endif + StopMainEventLoop(); +} + int main(int argc, char * argv[]) { - ChipLogProgress(AppServer, "chip_casting_simplified = 0"); // this file is built/run only if chip_casting_simplified = 0 + // This file is built/run only if chip_casting_simplified = 0 + ChipLogProgress(AppServer, "chip_casting_simplified = 0"); + +#if defined(ENABLE_CHIP_SHELL) + /* Block SIGINT and SIGTERM. Other threads created by the main thread + * will inherit the signal mask. Then we can explicitly unblock signals + * in the shell thread to handle them, so the read(stdin) call can be + * interrupted by a signal. */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + pthread_sigmask(SIG_BLOCK, &set, nullptr); +#endif + VerifyOrDie(CHIP_NO_ERROR == chip::Platform::MemoryInit()); VerifyOrDie(CHIP_NO_ERROR == chip::DeviceLayer::PlatformMgr().InitChipStack()); #if defined(ENABLE_CHIP_SHELL) Engine::Root().Init(); - std::thread shellThread([]() { Engine::Root().RunMainLoop(); }); Shell::RegisterCastingCommands(); + std::thread shellThread([]() { + sigset_t set_; + sigemptyset(&set_); + sigaddset(&set_, SIGINT); + sigaddset(&set_, SIGTERM); + // Unblock SIGINT and SIGTERM, so that the shell thread can handle + // them - we need read() call to be interrupted. + pthread_sigmask(SIG_UNBLOCK, &set_, nullptr); + Engine::Root().RunMainLoop(); + StopMainEventLoop(); + }); #endif + CHIP_ERROR err = CHIP_NO_ERROR; DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(CHIP_CONFIG_KVS_PATH); @@ -172,11 +213,25 @@ int main(int argc, char * argv[]) ProcessClusterCommand(argc, argv); } + { + struct sigaction sa = {}; + sa.sa_handler = StopSignalHandler; + sa.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sa, nullptr); + sigaction(SIGTERM, &sa, nullptr); + } + DeviceLayer::PlatformMgr().RunEventLoop(); + exit: + #if defined(ENABLE_CHIP_SHELL) shellThread.join(); #endif + + chip::Server::GetInstance().Shutdown(); + chip::DeviceLayer::PlatformMgr().Shutdown(); + if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Failed to run TV Casting App: %s", ErrorStr(err)); diff --git a/examples/tv-casting-app/linux/simple-app.cpp b/examples/tv-casting-app/linux/simple-app.cpp index 5526d6a3f6..a0863fa9e4 100644 --- a/examples/tv-casting-app/linux/simple-app.cpp +++ b/examples/tv-casting-app/linux/simple-app.cpp @@ -16,6 +16,8 @@ * limitations under the License. */ +#include + #include "simple-app-helper.h" #include "core/CastingPlayer.h" @@ -89,9 +91,37 @@ class CommonCaseDeviceServerInitParamsProvider : public ServerInitParamsProvider } }; +void StopMainEventLoop() +{ + chip::Server::GetInstance().GenerateShutDownEvent(); + chip::DeviceLayer::SystemLayer().ScheduleLambda([]() { chip::DeviceLayer::PlatformMgr().StopEventLoopTask(); }); +} + +void StopSignalHandler(int /* signal */) +{ +#if defined(ENABLE_CHIP_SHELL) + chip::Shell::Engine::Root().StopMainLoop(); +#endif + StopMainEventLoop(); +} + int main(int argc, char * argv[]) { - ChipLogProgress(AppServer, "chip_casting_simplified = 1"); // this file is built/run only if chip_casting_simplified = 1 + // This file is built/run only if chip_casting_simplified = 1 + ChipLogProgress(AppServer, "chip_casting_simplified = 1"); + +#if defined(ENABLE_CHIP_SHELL) + /* Block SIGINT and SIGTERM. Other threads created by the main thread + * will inherit the signal mask. Then we can explicitly unblock signals + * in the shell thread to handle them, so the read(stdin) call can be + * interrupted by a signal. */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + pthread_sigmask(SIG_BLOCK, &set, nullptr); +#endif + // Create AppParameters that need to be passed to CastingApp.Initialize() AppParameters appParameters; RotatingDeviceIdUniqueIdProvider rotatingDeviceIdUniqueIdProvider; @@ -122,8 +152,18 @@ int main(int argc, char * argv[]) #if defined(ENABLE_CHIP_SHELL) chip::Shell::Engine::Root().Init(); - std::thread shellThread([]() { chip::Shell::Engine::Root().RunMainLoop(); }); RegisterCommands(); + std::thread shellThread([]() { + sigset_t set_; + sigemptyset(&set_); + sigaddset(&set_, SIGINT); + sigaddset(&set_, SIGTERM); + // Unblock SIGINT and SIGTERM, so that the shell thread can handle + // them - we need read() call to be interrupted. + pthread_sigmask(SIG_UNBLOCK, &set_, nullptr); + chip::Shell::Engine::Root().RunMainLoop(); + StopMainEventLoop(); + }); #endif CastingPlayerDiscovery::GetInstance()->SetDelegate(DiscoveryDelegateImpl::GetInstance()); @@ -133,7 +173,20 @@ int main(int argc, char * argv[]) VerifyOrReturnValue(err == CHIP_NO_ERROR, -1, ChipLogError(AppServer, "CastingPlayerDiscovery::StartDiscovery failed %" CHIP_ERROR_FORMAT, err.Format())); + struct sigaction sa = {}; + sa.sa_handler = StopSignalHandler; + sa.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sa, nullptr); + sigaction(SIGTERM, &sa, nullptr); + chip::DeviceLayer::PlatformMgr().RunEventLoop(); +#if defined(ENABLE_CHIP_SHELL) + shellThread.join(); +#endif + + chip::Server::GetInstance().Shutdown(); + chip::DeviceLayer::PlatformMgr().Shutdown(); + return 0; } diff --git a/scripts/tests/run_tv_casting_test.py b/scripts/tests/run_tv_casting_test.py index 7b530c7a4a..fb02b2ad2f 100755 --- a/scripts/tests/run_tv_casting_test.py +++ b/scripts/tests/run_tv_casting_test.py @@ -17,7 +17,6 @@ import glob import logging import os -import signal import sys import tempfile import time @@ -32,7 +31,7 @@ """ This script can be used to validate the casting experience between the Linux tv-casting-app and the Linux tv-app. -It runs a series of test sequences that check for expected output lines from the tv-casting-app and the tv-app in +It runs a series of test sequences that check for expected output lines from the tv-casting-app and the tv-app in a deterministic order. If these lines are not found, it indicates an issue with the casting experience. """ @@ -92,24 +91,14 @@ def stop_app(test_sequence_name: str, app_name: str, app: ProcessOutputCapture): None, ) - if app_exit_code >= 0: + if app_exit_code != 0: raise TestStepException( f"{test_sequence_name}: {app_name} exited with unexpected exit code {app_exit_code}.", test_sequence_name, None, ) - signal_number = -app_exit_code - if signal_number != signal.SIGTERM.value: - raise TestStepException( - f"{test_sequence_name}: {app_name} stopped by signal {signal_number} instead of {signal.SIGTERM.value} (SIGTERM).", - test_sequence_name, - None, - ) - - logging.info( - f"{test_sequence_name}: {app_name} stopped by {signal_number} (SIGTERM) signal." - ) + logging.info(f"{test_sequence_name}: {app_name} stopped.") def parse_output_msg_in_subprocess( diff --git a/src/lib/shell/Engine.h b/src/lib/shell/Engine.h index a0d7cfa6fa..6307384db6 100644 --- a/src/lib/shell/Engine.h +++ b/src/lib/shell/Engine.h @@ -119,6 +119,13 @@ class Engine */ void RunMainLoop(); + /** + * Stop the shell mainloop on the next iteration. + * + * @note This method can be called from a signal handler to stop the main loop. + */ + void StopMainLoop() { mRunning = false; } + /** * Initialize the Shell::Engine. * @@ -130,6 +137,7 @@ class Engine private: static void ProcessShellLineTask(intptr_t context); + bool mRunning = true; }; } // namespace Shell diff --git a/src/lib/shell/MainLoopAmeba.cpp b/src/lib/shell/MainLoopAmeba.cpp index b8476a5dd9..4f5ea91bec 100644 --- a/src/lib/shell/MainLoopAmeba.cpp +++ b/src/lib/shell/MainLoopAmeba.cpp @@ -135,7 +135,7 @@ namespace Shell { void Engine::RunMainLoop() { char line[CHIP_SHELL_MAX_LINE_SIZE]; - while (true) + while (mRunning) { memset(line, 0, CHIP_SHELL_MAX_LINE_SIZE); if (ReadLine(line, CHIP_SHELL_MAX_LINE_SIZE) > 0u) diff --git a/src/lib/shell/MainLoopDefault.cpp b/src/lib/shell/MainLoopDefault.cpp index dba7639792..6a3a6b300b 100644 --- a/src/lib/shell/MainLoopDefault.cpp +++ b/src/lib/shell/MainLoopDefault.cpp @@ -15,13 +15,15 @@ * limitations under the License. */ -#include "streamer.h" +#include +#include +#include + #include #include #include -#include -#include +#include "streamer.h" using chip::FormatCHIPError; using chip::Platform::MemoryAlloc; @@ -46,11 +48,18 @@ size_t ReadLine(char * buffer, size_t max) break; } - if (streamer_read(streamer_get(), buffer + line_sz, 1) != 1) + auto ret = streamer_read(streamer_get(), buffer + line_sz, 1); + if (ret == -1 && errno == EINTR) { - continue; + streamer_printf(streamer_get(), "^C\r\n"); + // In case of EINTR (Ctrl-C) reset the buffer and start over. + buffer[line_sz = 0] = '\0'; + break; } + if (ret != 1) + continue; + // Process character we just read. switch (buffer[line_sz]) { @@ -188,7 +197,7 @@ void Engine::RunMainLoop() { streamer_printf(streamer_get(), CHIP_SHELL_PROMPT); - while (true) + while (mRunning) { char * line = static_cast(Platform::MemoryAlloc(CHIP_SHELL_MAX_LINE_SIZE)); if (ReadLine(line, CHIP_SHELL_MAX_LINE_SIZE) == 0u) diff --git a/src/lib/shell/MainLoopESP32.cpp b/src/lib/shell/MainLoopESP32.cpp index aecca35774..1c36a5ccf4 100644 --- a/src/lib/shell/MainLoopESP32.cpp +++ b/src/lib/shell/MainLoopESP32.cpp @@ -70,7 +70,7 @@ namespace Shell { void Engine::RunMainLoop() { - while (true) + while (mRunning) { const char * prompt = LOG_COLOR_I "> " LOG_RESET_COLOR; char * line = linenoise(prompt); diff --git a/src/lib/shell/MainLoopMW320.cpp b/src/lib/shell/MainLoopMW320.cpp index ea7ca5de0a..833c87a3bc 100644 --- a/src/lib/shell/MainLoopMW320.cpp +++ b/src/lib/shell/MainLoopMW320.cpp @@ -273,7 +273,7 @@ void Engine::RunMainLoop() Engine::Root().RegisterDefaultCommands(); RegisterMetaCommands(); - while (true) + while (mRunning) { streamer_printf(streamer_get(), CHIP_SHELL_PROMPT); diff --git a/src/lib/shell/MainLoopSilabs.cpp b/src/lib/shell/MainLoopSilabs.cpp index 8613c48b55..63c9d0ad6f 100644 --- a/src/lib/shell/MainLoopSilabs.cpp +++ b/src/lib/shell/MainLoopSilabs.cpp @@ -218,7 +218,7 @@ void Engine::RunMainLoop() { streamer_printf(streamer_get(), kShellPrompt); - while (true) + while (mRunning) { char * line = static_cast(Platform::MemoryAlloc(CHIP_SHELL_MAX_LINE_SIZE)); ReadLine(line, CHIP_SHELL_MAX_LINE_SIZE); From 7c557f6fbe9b1069d1135cb596d8f90e57c190bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Thu, 28 Nov 2024 16:11:43 +0100 Subject: [PATCH 108/219] Update light-switch-app/nrfconnect/README.md to fix privilege (#36657) Update light-switch-app/nrfconnect/README.md to fix privilege --- examples/light-switch-app/nrfconnect/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/light-switch-app/nrfconnect/README.md b/examples/light-switch-app/nrfconnect/README.md index 02f7b500aa..7869d71bf1 100644 --- a/examples/light-switch-app/nrfconnect/README.md +++ b/examples/light-switch-app/nrfconnect/README.md @@ -650,7 +650,7 @@ To perform the unicast binding process, complete the following steps: - `{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}` is an ACL for the communication with the CHIP Tool. - - `{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}` + - `{"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}, {"cluster": 8, "endpoint": 1, "deviceType": null}]}` is an ACL for binding (cluster no. 6 is the On/Off cluster and the cluster no. 8 is the Level Control cluster). From abc89a739c00a4875c0949b042671b99dd3a0d2c Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Thu, 28 Nov 2024 10:16:41 -0500 Subject: [PATCH 109/219] python.md: Add real example for run_python_test for the lighting_app (#36645) This PR adds a real example for running the `run_python_test.py` script against the `chip-lighting-app`. --- docs/testing/python.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/testing/python.md b/docs/testing/python.md index 4541871dcb..26a1dae1f4 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -631,6 +631,12 @@ example DUT on the host and includes factory reset support ./scripts/tests/run_python_test.py --factory-reset --app --app-args "whatever" --script --script-args "whatever" ``` +For example, to run TC-ACE-1.2 tests against the linux `chip-lighting-app`: + +```shell +./scripts/tests/run_python_test.py --factory-reset --app ./out/linux-x64-light-no-ble/chip-lighting-app --app-args "--trace-to json:log" --script src/python_testing/TC_ACE_1_2.py --script-args "--commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00" +``` + # Running tests in CI - Add test to the `repl_tests_linux` section of `.github/workflows/tests.yaml` From 406aca528c61f9834e206313bffca05a093cd115 Mon Sep 17 00:00:00 2001 From: Sergio Soares Date: Thu, 28 Nov 2024 11:27:32 -0500 Subject: [PATCH 110/219] python.md: Fix python_env command (#36641) * python.md: Fix python_env command This PR fixes the python activation command in the tutorial. From `source pyenv/bin/activate` to `source out/python_env/bin/activate` * Restyled by prettier-markdown --------- Co-authored-by: Restyled.io --- docs/testing/python.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/testing/python.md b/docs/testing/python.md index 26a1dae1f4..1db6ff779b 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -590,12 +590,11 @@ or bootstrap.sh should be used for for the first setup, activate.sh may be used for subsequent setups as it is faster. -Next build the python wheels and create / activate a venv (called `pyenv` here, -but any name may be used) +Next build the python wheels and create / activate a venv ``` ./scripts/build_python.sh -i out/python_env -source pyenv/bin/activate +source out/python_env/bin/activate ``` ## Running tests From 2e09ccc1215e86c183ea7e2c51301af2354cd0cb Mon Sep 17 00:00:00 2001 From: dinabenamar <108664279+dinabenamar@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:28:16 +0100 Subject: [PATCH 111/219] [NXP][platform][RT][RW61x] Disable "chip_inet_config_enable_tcp_endpoint" gn arg (#36665) * [NXP][platform][rt1060] Disable chip_inet_config_enable_tcp_endpoint Signed-off-by: Dina Benamar * [NXP][platform][rt1170] Disable chip_inet_config_enable_tcp_endpoint Signed-off-by: Dina Benamar * [NXP][platform][rw61x] Disable chip_inet_config_enable_tcp_endpoint Signed-off-by: Dina Benamar --------- Signed-off-by: Dina Benamar --- src/platform/nxp/rt/rt1060/args.gni | 3 +++ src/platform/nxp/rt/rt1170/args.gni | 3 +++ src/platform/nxp/rt/rw61x/args.gni | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/platform/nxp/rt/rt1060/args.gni b/src/platform/nxp/rt/rt1060/args.gni index b5fe5340f8..cca2833841 100644 --- a/src/platform/nxp/rt/rt1060/args.gni +++ b/src/platform/nxp/rt/rt1060/args.gni @@ -32,6 +32,9 @@ chip_ble_project_config_include = "" chip_build_tests = false +# Disable TCP endpoint. +chip_inet_config_enable_tcp_endpoint = false + #This enables the EventList global attribute enable_eventlist_attribute = true diff --git a/src/platform/nxp/rt/rt1170/args.gni b/src/platform/nxp/rt/rt1170/args.gni index aaadc3081a..9e5fdbdf06 100644 --- a/src/platform/nxp/rt/rt1170/args.gni +++ b/src/platform/nxp/rt/rt1170/args.gni @@ -32,6 +32,9 @@ chip_ble_project_config_include = "" chip_build_tests = false +# Disable TCP endpoint. +chip_inet_config_enable_tcp_endpoint = false + #This enables the EventList global attribute enable_eventlist_attribute = true diff --git a/src/platform/nxp/rt/rw61x/args.gni b/src/platform/nxp/rt/rw61x/args.gni index 543e1a1fe7..e008e7b13a 100644 --- a/src/platform/nxp/rt/rw61x/args.gni +++ b/src/platform/nxp/rt/rw61x/args.gni @@ -34,6 +34,9 @@ chip_ble_project_config_include = "" chip_build_tests = false +# Disable TCP endpoint. +chip_inet_config_enable_tcp_endpoint = false + declare_args() { spinel_interface_rpmsg = true From ddfc5df8d539ed9999d1f79c33472f8734b88b0e Mon Sep 17 00:00:00 2001 From: lucicop Date: Thu, 28 Nov 2024 19:09:30 +0200 Subject: [PATCH 112/219] Add skip_bytes functionality to OTA Provider and BDX downloader class (#36357) --- .../ota-provider-common/BdxOtaSender.cpp | 26 ++++++++++++++----- .../clusters/ota-requestor/BDXDownloader.cpp | 9 +++++++ .../clusters/ota-requestor/BDXDownloader.h | 2 +- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp b/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp index 871d8bfb19..12f6e76997 100644 --- a/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp +++ b/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp @@ -124,16 +124,24 @@ void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & ev break; } - case TransferSession::OutputEventType::kQueryReceived: { + case TransferSession::OutputEventType::kQueryReceived: + case TransferSession::OutputEventType::kQueryWithSkipReceived: { TransferSession::BlockData blockData; uint16_t blockSize = mTransfer.GetTransferBlockSize(); uint16_t bytesToRead = blockSize; + uint64_t bytesToSkip = 0; + + if (event.EventType == TransferSession::OutputEventType::kQueryWithSkipReceived) + { + bytesToSkip = event.bytesToSkip.BytesToSkip; + } + uint64_t seekOffset = mNumBytesSent + bytesToSkip; // TODO: This should be a utility function in TransferSession - if (mTransfer.GetTransferLength() > 0 && mNumBytesSent + blockSize > mTransfer.GetTransferLength()) + if ((mTransfer.GetTransferLength() > 0) && ((seekOffset + blockSize) > mTransfer.GetTransferLength())) { // cast should be safe because of condition above - bytesToRead = static_cast(mTransfer.GetTransferLength() - mNumBytesSent); + bytesToRead = static_cast(mTransfer.GetTransferLength() - seekOffset); } chip::System::PacketBufferHandle blockBuf = chip::System::PacketBufferHandle::New(bytesToRead); @@ -152,7 +160,13 @@ void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & ev return; } - otaFile.seekg(mNumBytesSent); + if (seekOffset > static_cast(std::numeric_limits::max())) + { + ChipLogError(BDX, "Seek offset too large"); + mTransfer.AbortTransfer(StatusCode::kLengthTooLarge); + return; + } + otaFile.seekg(static_cast(seekOffset)); otaFile.read(reinterpret_cast(blockBuf->Start()), bytesToRead); if (!(otaFile.good() || otaFile.eof())) { @@ -164,8 +178,8 @@ void BdxOtaSender::HandleTransferSessionOutput(TransferSession::OutputEvent & ev blockData.Data = blockBuf->Start(); blockData.Length = static_cast(otaFile.gcount()); blockData.IsEof = (blockData.Length < blockSize) || - (mNumBytesSent + static_cast(blockData.Length) == mTransfer.GetTransferLength() || (otaFile.peek() == EOF)); - mNumBytesSent = static_cast(mNumBytesSent + blockData.Length); + (seekOffset + static_cast(blockData.Length) == mTransfer.GetTransferLength() || (otaFile.peek() == EOF)); + mNumBytesSent = static_cast(seekOffset + blockData.Length); otaFile.close(); err = mTransfer.PrepareBlock(blockData); diff --git a/src/app/clusters/ota-requestor/BDXDownloader.cpp b/src/app/clusters/ota-requestor/BDXDownloader.cpp index 9c17cf0dde..43e3efca4a 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.cpp +++ b/src/app/clusters/ota-requestor/BDXDownloader.cpp @@ -159,6 +159,15 @@ CHIP_ERROR BDXDownloader::FetchNextData() return CHIP_NO_ERROR; } +CHIP_ERROR BDXDownloader::SkipData(uint32_t numBytes) +{ + VerifyOrReturnError(mState == State::kInProgress, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(mBdxTransfer.PrepareBlockQueryWithSkip(numBytes)); + PollTransferSession(); + + return CHIP_NO_ERROR; +} + void BDXDownloader::OnDownloadTimeout() { Reset(); diff --git a/src/app/clusters/ota-requestor/BDXDownloader.h b/src/app/clusters/ota-requestor/BDXDownloader.h index 121b59c027..69d1e8cc02 100644 --- a/src/app/clusters/ota-requestor/BDXDownloader.h +++ b/src/app/clusters/ota-requestor/BDXDownloader.h @@ -73,7 +73,7 @@ class BDXDownloader : public chip::OTADownloader // instead. void EndDownload(CHIP_ERROR reason = CHIP_NO_ERROR) override; CHIP_ERROR FetchNextData() override; - // TODO: override SkipData + CHIP_ERROR SkipData(uint32_t numBytes) override; System::Clock::Timeout GetTimeout(); // If True, there's been a timeout in the transfer as measured by no download progress after 'mTimeout' seconds. From a39c1787f083a829268055e333afd5cb73b0f971 Mon Sep 17 00:00:00 2001 From: Ricardo Casallas <77841255+rcasallas-silabs@users.noreply.github.com> Date: Thu, 28 Nov 2024 13:27:11 -0500 Subject: [PATCH 113/219] [Silabs] Trustzone-compatibility. (#36643) --- .../silabs/efr32/CHIPCryptoPALPsaEfr32.cpp | 308 +++++++----------- .../silabs/efr32/OTAImageProcessorImpl.cpp | 4 + .../silabs/platformAbstraction/GsdkSpam.cpp | 12 +- 3 files changed, 139 insertions(+), 185 deletions(-) diff --git a/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp b/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp index fc926ab5a8..0f3405d34c 100644 --- a/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp +++ b/src/platform/silabs/efr32/CHIPCryptoPALPsaEfr32.cpp @@ -43,12 +43,6 @@ #include "psa/crypto.h" -// Go straight for the driver wrappers for speed on plaintext keys -extern "C" { -#include "psa_crypto_core.h" -#include "psa_crypto_driver_wrappers.h" -} - // Includes needed for SPAKE2+ ECP operations #include #include @@ -439,139 +433,79 @@ CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_len CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length, uint8_t * out_buffer, size_t out_length) { - VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; - size_t output_length = 0; + VerifyOrReturnError(IsBufferNonEmpty(key, key_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsBufferNonEmpty(message, message_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr && out_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INVALID_ARGUMENT); - psa_crypto_init(); + const psa_algorithm_t algorithm = PSA_ALG_HMAC(PSA_ALG_SHA_256); + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + psa_key_attributes_t attrs = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t keyId = 0; - psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC); - psa_set_key_bits(&attr, key_length * 8); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + psa_set_key_type(&attrs, PSA_KEY_TYPE_HMAC); + psa_set_key_algorithm(&attrs, algorithm); + psa_set_key_usage_flags(&attrs, PSA_KEY_USAGE_SIGN_HASH); - status = psa_driver_wrapper_mac_compute(&attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_HMAC(PSA_ALG_SHA_256), - Uint8::to_const_uchar(message), message_length, out_buffer, out_length, &output_length); + status = psa_import_key(&attrs, key, key_length, &keyId); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + status = psa_mac_compute(keyId, algorithm, message, message_length, out_buffer, out_length, &out_length); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL); + exit: - psa_mac_abort(&operation); - psa_reset_key_attributes(&attr); - return error; + LogPsaError(status); + psa_destroy_key(keyId); + psa_reset_key_attributes(&attrs); + + return CHIP_NO_ERROR; } CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer, size_t out_length) { - return HMAC_SHA256(key.As(), sizeof(Symmetric128BitsKeyByteArray), message, message_length, - out_buffer, out_length); -} - -CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, - unsigned int iteration_count, uint32_t key_length, uint8_t * output) -{ - // TODO: replace inlined algorithm with usage of the PSA key derivation API once implemented - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - size_t output_length = 0; - - // Align these buffers on the native data size to speed up the XOR - static const size_t hash_size_in_native = - ((PSA_HASH_LENGTH(PSA_ALG_SHA_256) + sizeof(unsigned int) - 1) / sizeof(unsigned int)); - static_assert(hash_size_in_native * sizeof(unsigned int) >= PSA_HASH_LENGTH(PSA_ALG_SHA_256)); - - unsigned int md1_buffer[hash_size_in_native]; - unsigned int work_buffer[hash_size_in_native]; - uint8_t * md1 = (uint8_t *) md1_buffer; - uint8_t * work = (uint8_t *) work_buffer; - - size_t use_len; - unsigned char * out_p = output; - uint8_t * U1 = (uint8_t *) MemoryCalloc(1, slen + 4); - - VerifyOrExit(U1 != nullptr, error = CHIP_ERROR_NO_MEMORY); - VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsBufferNonEmpty(message, message_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(out_buffer != nullptr && out_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INVALID_ARGUMENT); - psa_crypto_init(); - - psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC); - psa_set_key_bits(&attr, plen * 8); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256)); - - // Start with initializing the salt + counter - memcpy(U1, salt, slen); - U1[slen] = 0; - U1[slen + 1] = 0; - U1[slen + 2] = 0; - U1[slen + 3] = 1; - - // Loop until we have generated the requested key length - while (key_length) - { - // U1 ends up in work - status = psa_driver_wrapper_mac_compute(&attr, password, plen, PSA_ALG_HMAC(PSA_ALG_SHA_256), U1, slen + 4, work, - PSA_HASH_LENGTH(PSA_ALG_SHA_256), &output_length); + const psa_algorithm_t algorithm = PSA_ALG_HMAC(PSA_ALG_SHA_256); + psa_status_t status = PSA_SUCCESS; - VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL); + status = psa_mac_compute(key.As(), algorithm, message, message_length, out_buffer, out_length, &out_length); + VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - memcpy(md1, work, PSA_HASH_LENGTH(PSA_ALG_SHA_256)); + return CHIP_NO_ERROR; +} - for (size_t i = 1; i < iteration_count; i++) - { - // U2 ends up in md1 - // +CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t pass_length, const uint8_t * salt, size_t salt_length, + unsigned int iteration_count, uint32_t key_length, uint8_t * key) +{ + VerifyOrReturnError(IsBufferNonEmpty(password, pass_length), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(salt_length >= kSpake2p_Min_PBKDF_Salt_Length && salt_length <= kSpake2p_Max_PBKDF_Salt_Length, + CHIP_ERROR_INVALID_ARGUMENT); - status = psa_driver_wrapper_mac_compute(&attr, password, plen, PSA_ALG_HMAC(PSA_ALG_SHA_256), md1, sizeof(md1_buffer), - md1, sizeof(md1_buffer), &output_length); + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; - VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL); + status = psa_key_derivation_setup(&operation, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - // U1 xor U2 - // - for (size_t j = 0; j < hash_size_in_native; j++) - { - work_buffer[j] ^= md1_buffer[j]; - } - } + status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, salt, salt_length); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - use_len = (key_length < PSA_HASH_LENGTH(PSA_ALG_SHA_256)) ? key_length : PSA_HASH_LENGTH(PSA_ALG_SHA_256); - memcpy(out_p, work, use_len); + status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, iteration_count); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - key_length -= (uint32_t) use_len; - out_p += use_len; + status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD, password, pass_length); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); - for (size_t i = 4; i > 0; i--) - { - if (++U1[slen + i - 1] != 0) - { - break; - } - } - } + status = psa_key_derivation_output_bytes(&operation, key, key_length); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); exit: - MemoryFree(U1); - psa_reset_key_attributes(&attr); + psa_key_derivation_abort(&operation); + return error; } @@ -656,62 +590,50 @@ static inline const psa_plaintext_ecp_keypair * to_const_keypair(const P256Keypa CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const { - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - size_t output_length = 0; - const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair); - - VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED); - VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED); + VerifyOrReturnError(IsBufferNonEmpty(msg, msg_length), CHIP_ERROR_INVALID_ARGUMENT); - psa_crypto_init(); + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + size_t outputLen = 0; + const PsaP256KeypairContext & context = ToConstPsaContext(mKeypair); - psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); - psa_set_key_bits(&attr, keypair->bitlen); - psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE); + status = psa_sign_message(context.key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg, msg_length, out_signature.Bytes(), + out_signature.Capacity(), &outputLen); - // use imported key to sign a message - status = - psa_driver_wrapper_sign_message(&attr, keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen), PSA_ALG_ECDSA(PSA_ALG_SHA_256), - msg, msg_length, out_signature.Bytes(), out_signature.Capacity(), &output_length); - - VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL); - VerifyOrReturnError(output_length == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INTERNAL); - VerifyOrReturnError(out_signature.SetLength(output_length) == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + VerifyOrExit(outputLen == kP256_ECDSA_Signature_Length_Raw, error = CHIP_ERROR_INTERNAL); + error = out_signature.SetLength(outputLen); exit: - _log_PSA_error(status); - psa_reset_key_attributes(&attr); - + LogPsaError(status); return error; } CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length, const P256ECDSASignature & signature) const { - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - - VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(IsBufferNonEmpty(msg, msg_length), CHIP_ERROR_INVALID_ARGUMENT); - psa_crypto_init(); + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + psa_key_id_t keyId = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); - psa_set_key_bits(&attr, 256); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_MESSAGE); - psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE); - // use imported key to verify a message - status = psa_driver_wrapper_verify_message(&attr, Uint8::to_const_uchar(*this), Length(), PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg, - msg_length, signature.ConstBytes(), signature.Length()); + status = psa_import_key(&attributes, ConstBytes(), Length(), &keyId); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + status = psa_verify_message(keyId, PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg, msg_length, signature.ConstBytes(), signature.Length()); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE); + exit: - _log_PSA_error(status); - psa_reset_key_attributes(&attr); + LogPsaError(status); + psa_destroy_key(keyId); + psa_reset_key_attributes(&attributes); return error; } @@ -719,30 +641,29 @@ CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, cons CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length, const P256ECDSASignature & signature) const { - VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(hash != nullptr && hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(signature.Length() == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INVALID_ARGUMENT); - CHIP_ERROR error = CHIP_NO_ERROR; - psa_status_t status = PSA_ERROR_BAD_STATE; - psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; - - // Step 1: import public key as volatile - psa_crypto_init(); + CHIP_ERROR error = CHIP_NO_ERROR; + psa_status_t status = PSA_SUCCESS; + psa_key_id_t keyId = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); - psa_set_key_bits(&attr, 256); - psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); - // use imported key to verify a hash - status = psa_driver_wrapper_verify_hash(&attr, Uint8::to_const_uchar(*this), Length(), PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, - hash_length, signature.ConstBytes(), signature.Length()); + status = psa_import_key(&attributes, ConstBytes(), Length(), &keyId); + VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL); + status = psa_verify_hash(keyId, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, hash_length, signature.ConstBytes(), signature.Length()); VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE); + exit: - _log_PSA_error(status); - psa_reset_key_attributes(&attr); + LogPsaError(status); + psa_destroy_key(keyId); + psa_reset_key_attributes(&attributes); + return error; } @@ -1204,20 +1125,43 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * o return CHIP_NO_ERROR; } -extern "C" { -#include "em_device.h" -} - #if defined(SEMAILBOX_PRESENT) // Add inlined optimisation which can use the SE to do point multiplication operations using // the ECDH primitive as a proxy for scalar multiplication. extern "C" { #include "sl_se_manager.h" #include "sl_se_manager_key_derivation.h" -#include "sl_se_manager_util.h" -#include "sli_se_driver_key_management.h" -#include "sli_se_manager_internal.h" } + +/** Pad size to word alignment + * Copied from: + * ${simplicity_sdk}/platform/security/sl_component/sl_psa_driver/inc/sli_se_driver_key_management.h + * @param size + * Unsigend integer type. + * @returns the number of padding bytes required + */ +#define sli_se_word_align(size) ((size + 3) & ~3) + +/** + * @brief + * Set the key desc to a plaintext key type pointing to data. + * Copied from: + * ${simplicity_sdk}/platform/security/sl_component/sl_psa_driver/inc/sli_se_driver_key_management.h + * @param[out] key_desc + * The SE manager key struct representing a key + * @param[in] data + * Buffer containing the key + * @param[in] data_length + * Length of the buffer + */ +static inline void key_descriptor_set_plaintext(sl_se_key_descriptor_t * key_desc, const uint8_t * data, size_t data_length) +{ + key_desc->storage.method = SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT; + key_desc->storage.location.buffer.pointer = (uint8_t *) data; + // TODO: Improve SE manager alignment requirements + key_desc->storage.location.buffer.size = sli_se_word_align(data_length); +} + #endif /* SEMAILBOX_PRESENT */ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1) @@ -1265,17 +1209,17 @@ CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, co // Set private key to scalar priv_desc.type = SL_SE_KEY_TYPE_ECC_P256; priv_desc.flags |= SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY; - sli_se_key_descriptor_set_plaintext(&priv_desc, scalar, sizeof(scalar)); + key_descriptor_set_plaintext(&priv_desc, scalar, sizeof(scalar)); // Set public key to point pub_desc.type = SL_SE_KEY_TYPE_ECC_P256; pub_desc.flags |= SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY; - sli_se_key_descriptor_set_plaintext(&pub_desc, point, sizeof(point)); + key_descriptor_set_plaintext(&pub_desc, point, sizeof(point)); // Set output to point shared_desc.type = SL_SE_KEY_TYPE_SYMMETRIC; shared_desc.size = sizeof(point); - sli_se_key_descriptor_set_plaintext(&shared_desc, point, sizeof(point)); + key_descriptor_set_plaintext(&shared_desc, point, sizeof(point)); // Re-init SE command context. sl_status = sl_se_init_command_context(&cmd_ctx); diff --git a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp index 09d37d0ca7..3699b36041 100644 --- a/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp +++ b/src/platform/silabs/efr32/OTAImageProcessorImpl.cpp @@ -224,7 +224,11 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) return; } #endif // SL_BTLCTRL_MUX +#if defined(SL_TRUSTZONE_NONSECURE) + CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId);) +#else CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);) +#endif if (err != SL_BOOTLOADER_OK) { ChipLogError(SoftwareUpdate, "bootloader_verifyImage() error: %ld", err); diff --git a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp index 361dfa93a4..bc221ead6a 100644 --- a/src/platform/silabs/platformAbstraction/GsdkSpam.cpp +++ b/src/platform/silabs/platformAbstraction/GsdkSpam.cpp @@ -126,7 +126,9 @@ CHIP_ERROR SilabsPlatform::Init(void) CHIP_ERROR SilabsPlatform::FlashInit() { -#if defined(_SILICON_LABS_32B_SERIES_2) +#if defined(SL_TRUSTZONE_NONSECURE) + return CHIP_ERROR_NOT_IMPLEMENTED; +#elif defined(_SILICON_LABS_32B_SERIES_2) MSC_Init(); #elif defined(_SILICON_LABS_32B_SERIES_3) sl_status_t status; @@ -140,7 +142,9 @@ CHIP_ERROR SilabsPlatform::FlashInit() CHIP_ERROR SilabsPlatform::FlashErasePage(uint32_t addr) { -#if defined(_SILICON_LABS_32B_SERIES_2) +#if defined(SL_TRUSTZONE_NONSECURE) + return CHIP_ERROR_NOT_IMPLEMENTED; +#elif defined(_SILICON_LABS_32B_SERIES_2) MSC_ErasePage((uint32_t *) addr); #elif defined(_SILICON_LABS_32B_SERIES_3) sl_status_t status; @@ -158,7 +162,9 @@ CHIP_ERROR SilabsPlatform::FlashErasePage(uint32_t addr) CHIP_ERROR SilabsPlatform::FlashWritePage(uint32_t addr, const uint8_t * data, size_t size) { -#if defined(_SILICON_LABS_32B_SERIES_2) +#if defined(SL_TRUSTZONE_NONSECURE) + return CHIP_ERROR_NOT_IMPLEMENTED; +#elif defined(_SILICON_LABS_32B_SERIES_2) MSC_WriteWord((uint32_t *) addr, data, size); #elif defined(_SILICON_LABS_32B_SERIES_3) sl_status_t status; From 439de24a545754ef4357c724310eaac7497134a2 Mon Sep 17 00:00:00 2001 From: lpbeliveau-silabs <112982107+lpbeliveau-silabs@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:08:02 -0500 Subject: [PATCH 114/219] [Silabs] Silabs Uart Shell fixes (#36667) * [SL-UP] Bugfix/silabs out rtt removal (#142) * [SL-UP] Bugfix/matter shell crash nullptr (#125) * Added checks on null ptr to prevent uart shell crash and modified ICD shell commands to be compatible with our internal structure --- examples/platform/silabs/shell/BUILD.gn | 10 +++++----- .../silabs/shell/{ => icd}/ICDShellCommands.cpp | 0 .../silabs/shell/{ => icd}/ICDShellCommands.h | 0 src/lib/shell/Engine.cpp | 2 ++ src/platform/silabs/Logging.cpp | 13 ++++--------- third_party/silabs/SiWx917_sdk.gni | 7 +++---- third_party/silabs/efr32_sdk.gni | 7 +++---- 7 files changed, 17 insertions(+), 22 deletions(-) rename examples/platform/silabs/shell/{ => icd}/ICDShellCommands.cpp (100%) rename examples/platform/silabs/shell/{ => icd}/ICDShellCommands.h (100%) diff --git a/examples/platform/silabs/shell/BUILD.gn b/examples/platform/silabs/shell/BUILD.gn index 74613aeac9..8d4cab328e 100644 --- a/examples/platform/silabs/shell/BUILD.gn +++ b/examples/platform/silabs/shell/BUILD.gn @@ -23,17 +23,17 @@ if (use_SiWx917) { shell_dependency_path = "${chip_root}/examples/platform/silabs/SiWx917" } -config("shell-config") { - include_dirs = [ "." ] +config("icd-shell-config") { + include_dirs = [ "./icd/" ] } source_set("icd") { sources = [ - "ICDShellCommands.cpp", - "ICDShellCommands.h", + "./icd/ICDShellCommands.cpp", + "./icd/ICDShellCommands.h", ] - public_configs = [ ":shell-config" ] + public_configs = [ ":icd-shell-config" ] deps = [ "${shell_dependency_path}:matter-shell" ] } diff --git a/examples/platform/silabs/shell/ICDShellCommands.cpp b/examples/platform/silabs/shell/icd/ICDShellCommands.cpp similarity index 100% rename from examples/platform/silabs/shell/ICDShellCommands.cpp rename to examples/platform/silabs/shell/icd/ICDShellCommands.cpp diff --git a/examples/platform/silabs/shell/ICDShellCommands.h b/examples/platform/silabs/shell/icd/ICDShellCommands.h similarity index 100% rename from examples/platform/silabs/shell/ICDShellCommands.h rename to examples/platform/silabs/shell/icd/ICDShellCommands.h diff --git a/src/lib/shell/Engine.cpp b/src/lib/shell/Engine.cpp index 809d44cc3c..ac91401281 100644 --- a/src/lib/shell/Engine.cpp +++ b/src/lib/shell/Engine.cpp @@ -86,6 +86,8 @@ CHIP_ERROR Engine::ExecCommand(int argc, char * argv[]) CHIP_ERROR retval = CHIP_ERROR_INVALID_ARGUMENT; VerifyOrReturnError(argc > 0, retval); + VerifyOrReturnError(nullptr != argv, retval); + // Find the command for (unsigned i = 0; i < _commandSetCount; i++) { diff --git a/src/platform/silabs/Logging.cpp b/src/platform/silabs/Logging.cpp index dea8913791..8b34308ba0 100644 --- a/src/platform/silabs/Logging.cpp +++ b/src/platform/silabs/Logging.cpp @@ -51,13 +51,8 @@ #include "uart.h" #endif -// Enable RTT by default -#ifndef SILABS_LOG_OUT_RTT -#define SILABS_LOG_OUT_RTT 1 -#endif - // SEGGER_RTT includes -#if SILABS_LOG_OUT_RTT +#if !SILABS_LOG_OUT_UART #include "SEGGER_RTT.h" #include "SEGGER_RTT_Conf.h" #endif @@ -136,7 +131,7 @@ static void PrintLog(const char * msg) SEGGER_RTT_WriteNoLock(LOG_RTT_BUFFER_INDEX, msg, sz); #endif // SILABS_LOG_OUT_UART -#if SILABS_LOG_OUT_RTT || PW_RPC_ENABLED +#if !SILABS_LOG_OUT_UART || PW_RPC_ENABLED const char * newline = "\r\n"; sz = strlen(newline); #if PW_RPC_ENABLED @@ -154,7 +149,7 @@ static void PrintLog(const char * msg) extern "C" void silabsInitLog(void) { #if SILABS_LOG_ENABLED -#if SILABS_LOG_OUT_RTT +#if !SILABS_LOG_OUT_UART #if LOG_RTT_BUFFER_INDEX != 0 SEGGER_RTT_ConfigUpBuffer(LOG_RTT_BUFFER_INDEX, LOG_RTT_BUFFER_NAME, sLogBuffer, LOG_RTT_BUFFER_SIZE, SEGGER_RTT_MODE_NO_BLOCK_TRIM); @@ -164,7 +159,7 @@ extern "C" void silabsInitLog(void) #else SEGGER_RTT_SetFlagsUpBuffer(LOG_RTT_BUFFER_INDEX, SEGGER_RTT_MODE_NO_BLOCK_TRIM); #endif -#endif // SILABS_LOG_OUT_RTT +#endif // !SILABS_LOG_OUT_UART #ifdef PW_RPC_ENABLED PigweedLogger::init(); diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni index 0bc8c7c693..63a0add4c4 100644 --- a/third_party/silabs/SiWx917_sdk.gni +++ b/third_party/silabs/SiWx917_sdk.gni @@ -331,10 +331,9 @@ template("siwx917_sdk") { } if (sl_uart_log_output) { - defines += [ - "SILABS_LOG_OUT_UART=1", - "SILABS_LOG_OUT_RTT=0", - ] + defines += [ "SILABS_LOG_OUT_UART=1" ] + } else { + defines += [ "SILABS_LOG_OUT_UART=0" ] } if (chip_build_libshell) { # matter shell diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni index 7861e827d7..bb621e0dce 100644 --- a/third_party/silabs/efr32_sdk.gni +++ b/third_party/silabs/efr32_sdk.gni @@ -487,10 +487,9 @@ template("efr32_sdk") { } if (sl_uart_log_output) { - defines += [ - "SILABS_LOG_OUT_UART=1", - "SILABS_LOG_OUT_RTT=0", - ] + defines += [ "SILABS_LOG_OUT_UART=1" ] + } else { + defines += [ "SILABS_LOG_OUT_UART=0" ] } if (use_silabs_thread_lib) { From 1805b3ecad8c516f5f2b6a678bf0cdf29877c449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Fri, 29 Nov 2024 01:41:08 +0100 Subject: [PATCH 115/219] Update energy-management-app README.md (#36662) * Update energy-management-app README.md Add link to `kBasicInstallationTestEvent` definition * Update README.md * Update README.md * Restyle * Update README.md Use commit it --- examples/energy-management-app/linux/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md index 637b80f95d..9bb1cd3820 100644 --- a/examples/energy-management-app/linux/README.md +++ b/examples/energy-management-app/linux/README.md @@ -595,8 +595,9 @@ Step-by-step: 1. Set the default TestEventTrigger (`0x0094000000000000`): -- `0x0094000000000000` corresponds to `kBasicInstallationTestEvent` from - `WaterHeadermanagementTestEventTriggerHandler.h` +- `0x0094000000000000` corresponds to + [`kBasicInstallationTestEvent`](https://github.com/project-chip/connectedhomeip/blob/5e3127f5ac61e13c572a968199280d90a9c19dce/src/app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h#L47) + from `WaterHeadermanagementTestEventTriggerHandler.h` - `hex:00010203...0e0f` is the `--enable-key` passed to the startup of chip-energy-management-app - `0x12344321` is the node-id that the app was commissioned on From b3e074c96e2a72fa427dbb1827ffa717ea97a6ac Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Fri, 29 Nov 2024 00:50:44 -0500 Subject: [PATCH 116/219] Remove Active flag when the readhandler is going to be destroyed (#36653) * remove Active flag when the readhandler is going to be destroyed * Restyled by clang-format --------- Co-authored-by: Restyled.io --- src/app/ReadHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 4794ead97e..43f9b9310d 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -152,6 +152,7 @@ ReadHandler::~ReadHandler() auto * appCallback = mManagementCallback.GetAppCallback(); if (mFlags.Has(ReadHandlerFlags::ActiveSubscription) && appCallback) { + mFlags.Clear(ReadHandlerFlags::ActiveSubscription); appCallback->OnSubscriptionTerminated(*this); } From 19cbdf498bd5cd207f90ad5b7ff48b4151d1db97 Mon Sep 17 00:00:00 2001 From: crlonxp <88241281+crlonxp@users.noreply.github.com> Date: Fri, 29 Nov 2024 15:28:03 +0800 Subject: [PATCH 117/219] Sync latest commits of the laundry-washer-app in nxp rw61x platform (#36664) * Fix Matter 1.3 certifiction TC-LWM-1.1 case that feature-map should be 0 Signed-off-by: Chin-Ran Lo (cherry picked from commit 21c40394dd0df65b1dd07e6cf9545f9d5cb1af25) * Update laundry washer ZAP file to pass TC-IDM-10.2/10.4/10.5 during Matter 1.4 SVE Signed-off-by: Oliver Fan [nxp toup][laundry-washer-app][common] Update laundry washer to pass TC-OPSTATE-2.6 during Matter 1.4 SVE Signed-off-by: Oliver Fan [nxp toup][laundry-washer-app][RW612][RTOS] Update RW612 RTOS laundry washer app to pass TC-OPSTATE-2.6 during Matter 1.4 SVE Signed-off-by: Oliver Fan [nxp toup][laundry-washer-app][RT1170][RTOS] Update RT1170+IW612 RTOS laundry washer app to pass TC-OPSTATE-2.6 during Matter 1.4 SVE Signed-off-by: Oliver Fan [nxp toup][laundry-washer-app][RW612][Zephyr] Update laundry washer to pass TC-OPSTATE-2.6, TC-IDM-10.2/10.4/10.5 during Matter 1.4 SVE Signed-off-by: Oliver Fan * Update RW/RT device types ZAP files to align with latest root node configuration updates done in thermostat zap configuration Signed-off-by: Lo,Chin-Ran * Update RT1060 RTOS laundry washer app to aligh with rw61x and rt1170 to pass TC-OPSTATE-2.6 Signed-off-by: Oliver Fan * Restyled by clang-format * Restyled by gn --------- Signed-off-by: Oliver Fan Signed-off-by: Lo,Chin-Ran Co-authored-by: Chin-Ran Lo Co-authored-by: Oliver Fan Co-authored-by: Restyled.io --- .../nxp/common/main/AppTask.cpp | 12 +- .../include/operational-state-delegate-impl.h | 120 - .../main/operational-state-delegate-impl.cpp | 142 - .../laundry-washer-app/nxp/rt/rt1060/BUILD.gn | 23 +- .../laundry-washer-app/nxp/rt/rt1170/BUILD.gn | 23 +- .../laundry-washer-app/nxp/rt/rw61x/BUILD.gn | 25 +- .../nxp/zap/laundry-washer-app.matter | 526 ++-- .../nxp/zap/laundry-washer-app.zap | 2340 +++++++++-------- .../nxp/zephyr/CMakeLists.txt | 5 +- 9 files changed, 1510 insertions(+), 1706 deletions(-) delete mode 100644 examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h delete mode 100644 examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp diff --git a/examples/laundry-washer-app/nxp/common/main/AppTask.cpp b/examples/laundry-washer-app/nxp/common/main/AppTask.cpp index 5d82dcf92e..b9cb8716db 100644 --- a/examples/laundry-washer-app/nxp/common/main/AppTask.cpp +++ b/examples/laundry-washer-app/nxp/common/main/AppTask.cpp @@ -22,6 +22,7 @@ #include "CHIPDeviceManager.h" #include "ICDUtil.h" #include +#include #include #include "static-supported-temperature-levels.h" @@ -85,8 +86,15 @@ static CHIP_ERROR cliOpState(int argc, char * argv[]) if (map_cmd_opstate.find(argv[0]) != map_cmd_opstate.end()) { - OperationalState::GetOperationalStateInstance()->SetOperationalState(map_cmd_opstate.at(argv[0])); - ChipLogDetail(Shell, "OpSState : Set to %s state", argv[0]); + auto error = OperationalState::GetOperationalStateInstance()->SetOperationalState(map_cmd_opstate.at(argv[0])); + ChipLogDetail(Shell, "OpSState : Set to %s state & CountdownTime", argv[0]); + if ((error == CHIP_NO_ERROR) && + (map_cmd_opstate.at(argv[0]) == to_underlying(chip::app::Clusters::OperationalState::OperationalStateEnum::kRunning))) + { + chip::app::Clusters::OperationalState::GenericOperationalError err( + to_underlying(chip::app::Clusters::OperationalState::ErrorStateEnum::kNoError)); + OperationalState::GetOperationalStateDelegate()->HandleStartStateCallback(err); + } if (!strcmp(argv[0], "error") && argc == 2) { OperationalState::Structs::ErrorStateStruct::Type err; diff --git a/examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h b/examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h deleted file mode 100644 index 79f2695eb0..0000000000 --- a/examples/laundry-washer-app/nxp/common/main/include/operational-state-delegate-impl.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * All rights reserved. - * - * 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. - */ - -#pragma once - -#include -#include -#include - -namespace chip { -namespace app { -namespace Clusters { - -namespace OperationalState { - -// This is an application level delegate to handle operational state commands according to the specific business logic. -class GenericOperationalStateDelegateImpl : public Delegate -{ -public: - /** - * Get the countdown time. This attribute is not used in this application. - * @return The current countdown time. - */ - app::DataModel::Nullable GetCountdownTime() override { return {}; }; - - /** - * Fills in the provided GenericOperationalState with the state at index `index` if there is one, - * or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of states. - * Note: This is used by the SDK to populate the operational state list attribute. If the contents of this list changes, - * the device SHALL call the Instance's ReportOperationalStateListChange method to report that this attribute has changed. - * @param index The index of the state, with 0 representing the first state. - * @param operationalState The GenericOperationalState is filled. - */ - CHIP_ERROR GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) override; - - /** - * Fills in the provided MutableCharSpan with the phase at index `index` if there is one, - * or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of phases. - * - * If CHIP_ERROR_NOT_FOUND is returned for index 0, that indicates that the PhaseList attribute is null - * (there are no phases defined at all). - * - * Note: This is used by the SDK to populate the phase list attribute. If the contents of this list changes, the - * device SHALL call the Instance's ReportPhaseListChange method to report that this attribute has changed. - * @param index The index of the phase, with 0 representing the first phase. - * @param operationalPhase The MutableCharSpan is filled. - */ - CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) override; - - // command callback - /** - * Handle Command Callback in application: Pause - * @param[out] get operational error after callback. - */ - void HandlePauseStateCallback(GenericOperationalError & err) override; - - /** - * Handle Command Callback in application: Resume - * @param[out] get operational error after callback. - */ - void HandleResumeStateCallback(GenericOperationalError & err) override; - - /** - * Handle Command Callback in application: Start - * @param[out] get operational error after callback. - */ - void HandleStartStateCallback(GenericOperationalError & err) override; - - /** - * Handle Command Callback in application: Stop - * @param[out] get operational error after callback. - */ - void HandleStopStateCallback(GenericOperationalError & err) override; - -protected: - Span mOperationalStateList; - Span mOperationalPhaseList; -}; - -// This is an application level delegate to handle operational state commands according to the specific business logic. -class OperationalStateDelegate : public GenericOperationalStateDelegateImpl -{ -private: - const GenericOperationalState opStateList[4] = { - GenericOperationalState(to_underlying(OperationalStateEnum::kStopped)), - GenericOperationalState(to_underlying(OperationalStateEnum::kRunning)), - GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)), - GenericOperationalState(to_underlying(OperationalStateEnum::kError)), - }; - -public: - OperationalStateDelegate() - { - GenericOperationalStateDelegateImpl::mOperationalStateList = Span(opStateList); - } -}; - -Instance * GetOperationalStateInstance(); - -void Shutdown(); - -} // namespace OperationalState -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp b/examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp deleted file mode 100644 index 961fc868ed..0000000000 --- a/examples/laundry-washer-app/nxp/common/main/operational-state-delegate-impl.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Copyright (c) 2023 Project CHIP Authors - * All rights reserved. - * - * 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. - */ -#include - -using namespace chip; -using namespace chip::app; -using namespace chip::app::Clusters; -using namespace chip::app::Clusters::OperationalState; - -CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) -{ - if (index >= mOperationalStateList.size()) - { - return CHIP_ERROR_NOT_FOUND; - } - operationalState = mOperationalStateList[index]; - return CHIP_NO_ERROR; -} - -CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, MutableCharSpan & operationalPhase) -{ - if (index >= mOperationalPhaseList.size()) - { - return CHIP_ERROR_NOT_FOUND; - } - return CopyCharSpanToMutableCharSpan(mOperationalPhaseList[index], operationalPhase); -} - -void GenericOperationalStateDelegateImpl::HandlePauseStateCallback(GenericOperationalError & err) -{ - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kPaused)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -void GenericOperationalStateDelegateImpl::HandleResumeStateCallback(GenericOperationalError & err) -{ - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalStateEnum::kRunning)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -void GenericOperationalStateDelegateImpl::HandleStartStateCallback(GenericOperationalError & err) -{ - uint8_t opState = GetInstance()->GetCurrentOperationalState(); - if (opState == to_underlying(OperationalStateEnum::kError)) - { - err.Set(to_underlying(ErrorStateEnum::kUnableToStartOrResume)); - return; - } - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalStateEnum::kRunning)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -void GenericOperationalStateDelegateImpl::HandleStopStateCallback(GenericOperationalError & err) -{ - // placeholder implementation - auto error = GetInstance()->SetOperationalState(to_underlying(OperationalStateEnum::kStopped)); - if (error == CHIP_NO_ERROR) - { - err.Set(to_underlying(ErrorStateEnum::kNoError)); - } - else - { - err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation)); - } -} - -// Init Operational State cluster - -static OperationalState::Instance * gOperationalStateInstance = nullptr; -static OperationalStateDelegate * gOperationalStateDelegate = nullptr; - -OperationalState::Instance * OperationalState::GetOperationalStateInstance() -{ - return gOperationalStateInstance; -} - -void OperationalState::Shutdown() -{ - if (gOperationalStateInstance != nullptr) - { - delete gOperationalStateInstance; - gOperationalStateInstance = nullptr; - } - if (gOperationalStateDelegate != nullptr) - { - delete gOperationalStateDelegate; - gOperationalStateDelegate = nullptr; - } -} - -void emberAfOperationalStateClusterInitCallback(chip::EndpointId endpointId) -{ - VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. - VerifyOrDie(gOperationalStateInstance == nullptr && gOperationalStateDelegate == nullptr); - - gOperationalStateDelegate = new OperationalStateDelegate; - EndpointId operationalStateEndpoint = 0x01; - gOperationalStateInstance = new OperationalState::Instance(gOperationalStateDelegate, operationalStateEndpoint); - - gOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)); - - gOperationalStateInstance->Init(); -} diff --git a/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn index ee1e896987..4e41741946 100644 --- a/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rt1060/BUILD.gn @@ -44,6 +44,8 @@ declare_args() { # Setup discriminator as argument setup_discriminator = 3840 + + chip_with_diag_logs_demo = true } example_platform_dir = @@ -116,6 +118,13 @@ rt_executable("laundry-washer") { defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] } + if (chip_with_diag_logs_demo) { + defines += [ + "CONFIG_DIAG_LOGS_DEMO=1", + "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", + ] + } + include_dirs = [ "../../common/main/include", "../../common/main", @@ -135,6 +144,17 @@ rt_executable("laundry-washer") { "../../common/main/main.cpp", ] + if (chip_with_diag_logs_demo) { + include_dirs += [ + "${common_example_dir}/diagnostic_logs/include", + "${chip_root}", + ] + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + # App common files include_dirs += [ "${common_example_dir}/icd/include", @@ -163,11 +183,10 @@ rt_executable("laundry-washer") { sources += [ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", "../../common/main/laundry-washer-mode.cpp", - "../../common/main/operational-state-delegate-impl.cpp", ] if (nxp_enable_matter_cli) { diff --git a/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn index 90be59719a..0e0e71e8c2 100644 --- a/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rt1170/BUILD.gn @@ -41,6 +41,8 @@ declare_args() { # Setup discriminator as argument setup_discriminator = 3840 + + chip_with_diag_logs_demo = true } example_platform_dir = @@ -106,6 +108,13 @@ rt_executable("laundry-washer-app") { defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] } + if (chip_with_diag_logs_demo) { + defines += [ + "CONFIG_DIAG_LOGS_DEMO=1", + "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", + ] + } + include_dirs = [ "../../common/main/include", "../../common/main", @@ -125,6 +134,17 @@ rt_executable("laundry-washer-app") { "../../common/main/main.cpp", ] + if (chip_with_diag_logs_demo) { + include_dirs += [ + "${common_example_dir}/diagnostic_logs/include", + "${chip_root}", + ] + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + # App common files include_dirs += [ "${common_example_dir}/icd/include", @@ -151,11 +171,10 @@ rt_executable("laundry-washer-app") { sources += [ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", "../../common/main/laundry-washer-mode.cpp", - "../../common/main/operational-state-delegate-impl.cpp", ] if (nxp_enable_matter_cli) { diff --git a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn index 063cf49b81..1ef89a3852 100644 --- a/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn +++ b/examples/laundry-washer-app/nxp/rt/rw61x/BUILD.gn @@ -1,5 +1,5 @@ # Copyright (c) 2021 Project CHIP Authors -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -42,6 +42,8 @@ declare_args() { # Setup discriminator as argument setup_discriminator = 3840 + + chip_with_diag_logs_demo = true } example_platform_dir = @@ -114,6 +116,13 @@ rt_executable("laundry-washer") { defines += [ "CONFIG_NET_L2_OPENTHREAD=1" ] } + if (chip_with_diag_logs_demo) { + defines += [ + "CONFIG_DIAG_LOGS_DEMO=1", + "CHIP_DEVICE_CONFIG_MAX_DIAG_LOG_SIZE=1024", + ] + } + include_dirs = [ "../../common/main/include", "../../common/main", @@ -133,6 +142,17 @@ rt_executable("laundry-washer") { "../../common/main/main.cpp", ] + if (chip_with_diag_logs_demo) { + include_dirs += [ + "${common_example_dir}/diagnostic_logs/include", + "${chip_root}", + ] + sources += [ + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsDemo.cpp", + "${common_example_dir}/diagnostic_logs/source/DiagnosticLogsProviderDelegateImpl.cpp", + ] + } + if (nxp_enable_secure_whole_factory_data || nxp_enable_secure_EL2GO_factory_data) { sources += [ "${chip_root}/examples/platform/nxp/${nxp_platform}/factory_data/source/AppFactoryDataExample.cpp" ] @@ -173,11 +193,10 @@ rt_executable("laundry-washer") { sources += [ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp", + "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp", - "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp", "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp", "../../common/main/laundry-washer-mode.cpp", - "../../common/main/operational-state-delegate-impl.cpp", ] if (nxp_enable_matter_cli) { diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter index 28a2f46d28..37b7786af9 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.matter @@ -870,6 +870,23 @@ cluster OtaSoftwareUpdateRequestor = 42 { command AnnounceOTAProvider(AnnounceOTAProviderRequest): DefaultSuccess = 0; } +/** Nodes should be expected to be deployed to any and all regions of the world. These global regions + may have differing common languages, units of measurements, and numerical formatting + standards. As such, Nodes that visually or audibly convey information need a mechanism by which + they can be configured to use a user’s preferred language, units, etc */ +cluster LocalizationConfiguration = 43 { + revision 1; // NOTE: Default/not specifically set + + attribute access(write: manage) char_string<35> activeLocale = 0; + readonly attribute char_string supportedLocales[] = 1; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; +} + /** Nodes should be expected to be deployed to any and all regions of the world. These global regions may have differing preferences for the units in which values are conveyed in communication to a user. As such, Nodes that visually or audibly convey measurable values to the user need a @@ -896,265 +913,6 @@ cluster UnitLocalization = 45 { readonly attribute int16u clusterRevision = 65533; } -/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ -cluster PowerSource = 47 { - revision 1; // NOTE: Default/not specifically set - - enum BatApprovedChemistryEnum : enum16 { - kUnspecified = 0; - kAlkaline = 1; - kLithiumCarbonFluoride = 2; - kLithiumChromiumOxide = 3; - kLithiumCopperOxide = 4; - kLithiumIronDisulfide = 5; - kLithiumManganeseDioxide = 6; - kLithiumThionylChloride = 7; - kMagnesium = 8; - kMercuryOxide = 9; - kNickelOxyhydride = 10; - kSilverOxide = 11; - kZincAir = 12; - kZincCarbon = 13; - kZincChloride = 14; - kZincManganeseDioxide = 15; - kLeadAcid = 16; - kLithiumCobaltOxide = 17; - kLithiumIon = 18; - kLithiumIonPolymer = 19; - kLithiumIronPhosphate = 20; - kLithiumSulfur = 21; - kLithiumTitanate = 22; - kNickelCadmium = 23; - kNickelHydrogen = 24; - kNickelIron = 25; - kNickelMetalHydride = 26; - kNickelZinc = 27; - kSilverZinc = 28; - kSodiumIon = 29; - kSodiumSulfur = 30; - kZincBromide = 31; - kZincCerium = 32; - } - - enum BatChargeFaultEnum : enum8 { - kUnspecified = 0; - kAmbientTooHot = 1; - kAmbientTooCold = 2; - kBatteryTooHot = 3; - kBatteryTooCold = 4; - kBatteryAbsent = 5; - kBatteryOverVoltage = 6; - kBatteryUnderVoltage = 7; - kChargerOverVoltage = 8; - kChargerUnderVoltage = 9; - kSafetyTimeout = 10; - } - - enum BatChargeLevelEnum : enum8 { - kOK = 0; - kWarning = 1; - kCritical = 2; - } - - enum BatChargeStateEnum : enum8 { - kUnknown = 0; - kIsCharging = 1; - kIsAtFullCharge = 2; - kIsNotCharging = 3; - } - - enum BatCommonDesignationEnum : enum16 { - kUnspecified = 0; - kAAA = 1; - kAA = 2; - kC = 3; - kD = 4; - k4v5 = 5; - k6v0 = 6; - k9v0 = 7; - k12AA = 8; - kAAAA = 9; - kA = 10; - kB = 11; - kF = 12; - kN = 13; - kNo6 = 14; - kSubC = 15; - kA23 = 16; - kA27 = 17; - kBA5800 = 18; - kDuplex = 19; - k4SR44 = 20; - k523 = 21; - k531 = 22; - k15v0 = 23; - k22v5 = 24; - k30v0 = 25; - k45v0 = 26; - k67v5 = 27; - kJ = 28; - kCR123A = 29; - kCR2 = 30; - k2CR5 = 31; - kCRP2 = 32; - kCRV3 = 33; - kSR41 = 34; - kSR43 = 35; - kSR44 = 36; - kSR45 = 37; - kSR48 = 38; - kSR54 = 39; - kSR55 = 40; - kSR57 = 41; - kSR58 = 42; - kSR59 = 43; - kSR60 = 44; - kSR63 = 45; - kSR64 = 46; - kSR65 = 47; - kSR66 = 48; - kSR67 = 49; - kSR68 = 50; - kSR69 = 51; - kSR516 = 52; - kSR731 = 53; - kSR712 = 54; - kLR932 = 55; - kA5 = 56; - kA10 = 57; - kA13 = 58; - kA312 = 59; - kA675 = 60; - kAC41E = 61; - k10180 = 62; - k10280 = 63; - k10440 = 64; - k14250 = 65; - k14430 = 66; - k14500 = 67; - k14650 = 68; - k15270 = 69; - k16340 = 70; - kRCR123A = 71; - k17500 = 72; - k17670 = 73; - k18350 = 74; - k18500 = 75; - k18650 = 76; - k19670 = 77; - k25500 = 78; - k26650 = 79; - k32600 = 80; - } - - enum BatFaultEnum : enum8 { - kUnspecified = 0; - kOverTemp = 1; - kUnderTemp = 2; - } - - enum BatReplaceabilityEnum : enum8 { - kUnspecified = 0; - kNotReplaceable = 1; - kUserReplaceable = 2; - kFactoryReplaceable = 3; - } - - enum PowerSourceStatusEnum : enum8 { - kUnspecified = 0; - kActive = 1; - kStandby = 2; - kUnavailable = 3; - } - - enum WiredCurrentTypeEnum : enum8 { - kAC = 0; - kDC = 1; - } - - enum WiredFaultEnum : enum8 { - kUnspecified = 0; - kOverVoltage = 1; - kUnderVoltage = 2; - } - - bitmap Feature : bitmap32 { - kWired = 0x1; - kBattery = 0x2; - kRechargeable = 0x4; - kReplaceable = 0x8; - } - - struct BatChargeFaultChangeType { - BatChargeFaultEnum current[] = 0; - BatChargeFaultEnum previous[] = 1; - } - - struct BatFaultChangeType { - BatFaultEnum current[] = 0; - BatFaultEnum previous[] = 1; - } - - struct WiredFaultChangeType { - WiredFaultEnum current[] = 0; - WiredFaultEnum previous[] = 1; - } - - info event WiredFaultChange = 0 { - WiredFaultEnum current[] = 0; - WiredFaultEnum previous[] = 1; - } - - info event BatFaultChange = 1 { - BatFaultEnum current[] = 0; - BatFaultEnum previous[] = 1; - } - - info event BatChargeFaultChange = 2 { - BatChargeFaultEnum current[] = 0; - BatChargeFaultEnum previous[] = 1; - } - - readonly attribute PowerSourceStatusEnum status = 0; - readonly attribute int8u order = 1; - readonly attribute char_string<60> description = 2; - readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; - readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; - readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; - readonly attribute optional nullable int32u wiredAssessedCurrent = 6; - readonly attribute optional int32u wiredNominalVoltage = 7; - readonly attribute optional int32u wiredMaximumCurrent = 8; - readonly attribute optional boolean wiredPresent = 9; - readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; - readonly attribute optional nullable int32u batVoltage = 11; - readonly attribute optional nullable int8u batPercentRemaining = 12; - readonly attribute optional nullable int32u batTimeRemaining = 13; - readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; - readonly attribute optional boolean batReplacementNeeded = 15; - readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; - readonly attribute optional boolean batPresent = 17; - readonly attribute optional BatFaultEnum activeBatFaults[] = 18; - readonly attribute optional char_string<60> batReplacementDescription = 19; - readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; - readonly attribute optional char_string<20> batANSIDesignation = 21; - readonly attribute optional char_string<20> batIECDesignation = 22; - readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; - readonly attribute optional int32u batCapacity = 24; - readonly attribute optional int8u batQuantity = 25; - readonly attribute optional BatChargeStateEnum batChargeState = 26; - readonly attribute optional nullable int32u batTimeToFullCharge = 27; - readonly attribute optional boolean batFunctionalWhileCharging = 28; - readonly attribute optional nullable int32u batChargingCurrent = 29; - readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; - readonly attribute endpoint_no endpointList[] = 31; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; -} - /** This cluster is used to manage global aspects of the Commissioning flow. */ cluster GeneralCommissioning = 48 { revision 1; // NOTE: Default/not specifically set @@ -1427,6 +1185,53 @@ cluster NetworkCommissioning = 49 { command access(invoke: administer) QueryIdentity(QueryIdentityRequest): QueryIdentityResponse = 9; } +/** The cluster provides commands for retrieving unstructured diagnostic logs from a Node that may be used to aid in diagnostics. */ +cluster DiagnosticLogs = 50 { + revision 1; // NOTE: Default/not specifically set + + enum IntentEnum : enum8 { + kEndUserSupport = 0; + kNetworkDiag = 1; + kCrashLogs = 2; + } + + enum StatusEnum : enum8 { + kSuccess = 0; + kExhausted = 1; + kNoLogs = 2; + kBusy = 3; + kDenied = 4; + } + + enum TransferProtocolEnum : enum8 { + kResponsePayload = 0; + kBDX = 1; + } + + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct RetrieveLogsRequestRequest { + IntentEnum intent = 0; + TransferProtocolEnum requestedProtocol = 1; + optional char_string<32> transferFileDesignator = 2; + } + + response struct RetrieveLogsResponse = 1 { + StatusEnum status = 0; + long_octet_string logContent = 1; + optional epoch_us UTCTimeStamp = 2; + optional systime_us timeSinceBoot = 3; + } + + /** Retrieving diagnostic logs from a Node */ + command RetrieveLogsRequest(RetrieveLogsRequestRequest): RetrieveLogsResponse = 0; +} + /** The General Diagnostics Cluster, along with other diagnostics clusters, provide a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ cluster GeneralDiagnostics = 51 { revision 2; @@ -1558,6 +1363,43 @@ cluster GeneralDiagnostics = 51 { command PayloadTestRequest(PayloadTestRequestRequest): PayloadTestResponse = 3; } +/** The Software Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ +cluster SoftwareDiagnostics = 52 { + revision 1; // NOTE: Default/not specifically set + + bitmap Feature : bitmap32 { + kWatermarks = 0x1; + } + + struct ThreadMetricsStruct { + int64u id = 0; + optional char_string<8> name = 1; + optional int32u stackFreeCurrent = 2; + optional int32u stackFreeMinimum = 3; + optional int32u stackSize = 4; + } + + info event SoftwareFault = 0 { + int64u id = 0; + optional char_string name = 1; + optional octet_string faultRecording = 2; + } + + readonly attribute optional ThreadMetricsStruct threadMetrics[] = 0; + readonly attribute optional int64u currentHeapFree = 1; + readonly attribute optional int64u currentHeapUsed = 2; + readonly attribute optional int64u currentHeapHighWatermark = 3; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute event_id eventList[] = 65530; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + /** Reception of this command SHALL reset the values: The StackFreeMinimum field of the ThreadMetrics attribute, CurrentHeapHighWaterMark attribute. */ + command access(invoke: manage) ResetWatermarks(): DefaultSuccess = 0; +} + /** The Wi-Fi Network Diagnostics Cluster provides a means to acquire standardized diagnostics metrics that MAY be used by a Node to assist a user or Administrative Node in diagnosing potential problems. */ cluster WiFiNetworkDiagnostics = 54 { revision 1; // NOTE: Default/not specifically set @@ -1926,46 +1768,6 @@ cluster UserLabel = 65 { readonly attribute int16u clusterRevision = 65533; } -/** Attributes and commands for selecting a mode from a list of supported options. */ -cluster ModeSelect = 80 { - revision 2; - - bitmap Feature : bitmap32 { - kOnOff = 0x1; - } - - struct SemanticTagStruct { - vendor_id mfgCode = 0; - enum16 value = 1; - } - - struct ModeOptionStruct { - char_string<64> label = 0; - int8u mode = 1; - SemanticTagStruct semanticTags[] = 2; - } - - readonly attribute char_string<64> description = 0; - readonly attribute nullable enum16 standardNamespace = 1; - readonly attribute ModeOptionStruct supportedModes[] = 2; - readonly attribute int8u currentMode = 3; - attribute optional nullable int8u startUpMode = 4; - attribute optional nullable int8u onMode = 5; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct ChangeToModeRequest { - int8u newMode = 0; - } - - /** On receipt of this command, if the NewMode field matches the Mode field in an entry of the SupportedModes list, the server SHALL set the CurrentMode attribute to the NewMode value, otherwise, the server SHALL respond with an INVALID_COMMAND status response. */ - command ChangeToMode(ChangeToModeRequest): DefaultSuccess = 0; -} - /** Attributes and commands for selecting a mode from a list of supported options. */ cluster LaundryWasherMode = 81 { revision 2; @@ -2154,7 +1956,8 @@ cluster OperationalState = 96 { } endpoint 0 { - device type ma_rootdevice = 22, version 1; + device type ma_rootdevice = 22, version 0; + device type ma_otarequestor = 18, version 1; binding cluster OtaSoftwareUpdateProvider; @@ -2163,6 +1966,9 @@ endpoint 0 { callback attribute serverList; callback attribute clientList; callback attribute partsList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; } @@ -2171,10 +1977,11 @@ endpoint 0 { emits event AccessControlEntryChanged; emits event AccessControlExtensionChanged; callback attribute acl; - callback attribute extension; callback attribute subjectsPerAccessControlEntry; callback attribute targetsPerAccessControlEntry; callback attribute accessControlEntriesPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; callback attribute clusterRevision; @@ -2182,28 +1989,19 @@ endpoint 0 { server cluster BasicInformation { emits event StartUp; - emits event ShutDown; - emits event Leave; callback attribute dataModelRevision; callback attribute vendorName; callback attribute vendorID; callback attribute productName; callback attribute productID; - persist attribute nodeLabel; + ram attribute nodeLabel; callback attribute location; callback attribute hardwareVersion; callback attribute hardwareVersionString; callback attribute softwareVersion; callback attribute softwareVersionString; - callback attribute manufacturingDate; - callback attribute partNumber; - callback attribute productURL; - callback attribute productLabel; - callback attribute serialNumber; - persist attribute localConfigDisabled default = 0; callback attribute uniqueID; callback attribute capabilityMinima; - callback attribute productAppearance; callback attribute specificationVersion; callback attribute maxPathsPerInvoke; callback attribute generatedCommandList; @@ -2230,7 +2028,9 @@ endpoint 0 { handle command AnnounceOTAProvider; } - server cluster UnitLocalization { + server cluster LocalizationConfiguration { + ram attribute activeLocale; + callback attribute supportedLocales; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; @@ -2238,14 +2038,26 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster UnitLocalization { + ram attribute temperatureUnit; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 1; + ram attribute clusterRevision default = 1; + } + server cluster GeneralCommissioning { ram attribute breadcrumb default = 0x0000000000000000; callback attribute basicCommissioningInfo; callback attribute regulatoryConfig; callback attribute locationCapability; callback attribute supportsConcurrentConnection; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ArmFailSafe; handle command ArmFailSafeResponse; @@ -2264,11 +2076,12 @@ endpoint 0 { ram attribute lastNetworkingStatus; ram attribute lastNetworkID; ram attribute lastConnectErrorValue; + callback attribute supportedWiFiBands; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 2; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 3; handle command ScanNetworks; handle command ScanNetworksResponse; @@ -2281,6 +2094,17 @@ endpoint 0 { handle command ReorderNetwork; } + server cluster DiagnosticLogs { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 1; + + handle command RetrieveLogsRequest; + handle command RetrieveLogsResponse; + } + server cluster GeneralDiagnostics { emits event BootReason; callback attribute networkInterfaces; @@ -2300,24 +2124,53 @@ endpoint 0 { handle command TimeSnapshotResponse; } + server cluster SoftwareDiagnostics { + callback attribute threadMetrics; + callback attribute currentHeapFree; + callback attribute currentHeapUsed; + callback attribute currentHeapHighWatermark; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + + handle command ResetWatermarks; + } + server cluster WiFiNetworkDiagnostics { + emits event Disconnection; + emits event AssociationFailure; + emits event ConnectionStatus; callback attribute bssid; callback attribute securityType; callback attribute wiFiVersion; callback attribute channelNumber; callback attribute rssi; + callback attribute beaconLostCount; + callback attribute beaconRxCount; + callback attribute packetMulticastRxCount; + callback attribute packetMulticastTxCount; + callback attribute packetUnicastRxCount; + callback attribute packetUnicastTxCount; callback attribute currentMaxRate; + callback attribute overrunCount; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 0; + ram attribute featureMap default = 3; ram attribute clusterRevision default = 1; + + handle command ResetCounts; } server cluster AdministratorCommissioning { callback attribute windowStatus; callback attribute adminFabricIndex; callback attribute adminVendorId; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2332,6 +2185,9 @@ endpoint 0 { callback attribute commissionedFabrics; callback attribute trustedRootCertificates; callback attribute currentFabricIndex; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 1; @@ -2354,6 +2210,9 @@ endpoint 0 { callback attribute groupTable; callback attribute maxGroupsPerFabric; callback attribute maxGroupKeysPerFabric; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; callback attribute featureMap; callback attribute clusterRevision; @@ -2411,8 +2270,8 @@ endpoint 1 { callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute attributeList; - ram attribute featureMap default = 1; - ram attribute clusterRevision default = 5; + ram attribute featureMap default = 2; + ram attribute clusterRevision default = 6; handle command Off; handle command On; @@ -2443,19 +2302,6 @@ endpoint 1 { ram attribute clusterRevision default = 1; } - server cluster PowerSource { - ram attribute status; - ram attribute order; - ram attribute description; - ram attribute wiredCurrentType; - callback attribute endpointList; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 1; - ram attribute clusterRevision default = 2; - } - server cluster FixedLabel { callback attribute labelList; callback attribute generatedCommandList; @@ -2474,22 +2320,6 @@ endpoint 1 { ram attribute clusterRevision default = 1; } - server cluster ModeSelect { - ram attribute description; - ram attribute standardNamespace; - callback attribute supportedModes; - ram attribute currentMode; - ram attribute startUpMode; - ram attribute onMode; - callback attribute generatedCommandList; - callback attribute acceptedCommandList; - callback attribute attributeList; - ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; - - handle command ChangeToMode; - } - server cluster LaundryWasherMode { callback attribute supportedModes; callback attribute currentMode; @@ -2499,7 +2329,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command ChangeToMode; handle command ChangeToModeResponse; @@ -2542,7 +2372,7 @@ endpoint 1 { callback attribute acceptedCommandList; callback attribute attributeList; ram attribute featureMap default = 0; - ram attribute clusterRevision default = 1; + ram attribute clusterRevision default = 2; handle command Pause; handle command Stop; diff --git a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap index 8af4eaa897..9a8d968d15 100644 --- a/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap +++ b/examples/laundry-washer-app/nxp/zap/laundry-washer-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -38,27 +38,38 @@ "id": 1, "name": "MA-rootdevice", "deviceTypeRef": { - "code": 22, + "code": 18, "profileId": 259, - "label": "MA-rootdevice", - "name": "MA-rootdevice" + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 }, "deviceTypes": [ + { + "code": 18, + "profileId": 259, + "label": "MA-otarequestor", + "name": "MA-otarequestor", + "deviceTypeOrder": 0 + }, { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 1 } ], "deviceVersions": [ - 1 + 1, + 0 ], "deviceIdentifiers": [ + 18, 22 ], - "deviceTypeName": "MA-rootdevice", - "deviceTypeCode": 22, + "deviceTypeName": "MA-otarequestor", + "deviceTypeCode": 18, "deviceTypeProfileId": 259, "clusters": [ { @@ -133,6 +144,54 @@ "maxInterval": 65344, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -192,11 +251,11 @@ "reportableChange": 0 }, { - "name": "Extension", - "code": 1, + "name": "SubjectsPerAccessControlEntry", + "code": 2, "mfgCode": null, "side": "server", - "type": "array", + "type": "int16u", "included": 1, "storageOption": "External", "singleton": 0, @@ -208,8 +267,8 @@ "reportableChange": 0 }, { - "name": "SubjectsPerAccessControlEntry", - "code": 2, + "name": "TargetsPerAccessControlEntry", + "code": 3, "mfgCode": null, "side": "server", "type": "int16u", @@ -224,8 +283,8 @@ "reportableChange": 0 }, { - "name": "TargetsPerAccessControlEntry", - "code": 3, + "name": "AccessControlEntriesPerFabric", + "code": 4, "mfgCode": null, "side": "server", "type": "int16u", @@ -240,11 +299,27 @@ "reportableChange": 0 }, { - "name": "AccessControlEntriesPerFabric", - "code": 4, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -416,7 +491,7 @@ "side": "server", "type": "char_string", "included": 1, - "storageOption": "NVM", + "storageOption": "RAM", "singleton": 1, "bounded": 0, "defaultValue": "", @@ -501,104 +576,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ManufacturingDate", - "code": 11, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "PartNumber", - "code": 12, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductURL", - "code": 13, - "mfgCode": null, - "side": "server", - "type": "long_char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "ProductLabel", - "code": 14, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "SerialNumber", - "code": 15, - "mfgCode": null, - "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "LocalConfigDisabled", - "code": 16, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 1, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -625,22 +604,6 @@ "type": "CapabilityMinimaStruct", "included": 1, "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ProductAppearance", - "code": 20, - "mfgCode": null, - "side": "server", - "type": "ProductAppearanceStruct", - "included": 1, - "storageOption": "External", "singleton": 1, "bounded": 0, "defaultValue": null, @@ -713,22 +676,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 1, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -785,20 +732,6 @@ "mfgCode": null, "side": "server", "included": 1 - }, - { - "name": "ShutDown", - "code": 1, - "mfgCode": null, - "side": "server", - "included": 1 - }, - { - "name": "Leave", - "code": 2, - "mfgCode": null, - "side": "server", - "included": 1 } ] }, @@ -966,22 +899,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -1056,32 +973,32 @@ ] }, { - "name": "Unit Localization", - "code": 45, + "name": "Localization Configuration", + "code": 43, "mfgCode": null, - "define": "UNIT_LOCALIZATION_CLUSTER", + "define": "LOCALIZATION_CONFIGURATION_CLUSTER", "side": "server", "enabled": 1, "attributes": [ { - "name": "GeneratedCommandList", - "code": 65528, + "name": "ActiveLocale", + "code": 0, "mfgCode": null, "side": "server", - "type": "array", + "type": "char_string", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "SupportedLocales", + "code": 1, "mfgCode": null, "side": "server", "type": "array", @@ -1096,8 +1013,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1112,8 +1029,24 @@ "reportableChange": 0 }, { - "name": "AttributeList", - "code": 65531, + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", "type": "array", @@ -1161,6 +1094,112 @@ } ] }, + { + "name": "Unit Localization", + "code": 45, + "mfgCode": null, + "define": "UNIT_LOCALIZATION_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "TemperatureUnit", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "TempUnitEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "General Commissioning", "code": 48, @@ -1299,6 +1338,54 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "FeatureMap", "code": 65532, @@ -1325,7 +1412,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1544,8 +1631,8 @@ "reportableChange": 0 }, { - "name": "GeneratedCommandList", - "code": 65528, + "name": "SupportedWiFiBands", + "code": 8, "mfgCode": null, "side": "server", "type": "array", @@ -1560,8 +1647,8 @@ "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1576,8 +1663,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -1633,7 +1720,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "3", "reportable": 1, "minInterval": 0, "maxInterval": 65344, @@ -1642,15 +1729,15 @@ ] }, { - "name": "General Diagnostics", - "code": 51, + "name": "Diagnostic Logs", + "code": 50, "mfgCode": null, - "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "define": "DIAGNOSTIC_LOGS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "TestEventTrigger", + "name": "RetrieveLogsRequest", "code": 0, "mfgCode": null, "source": "client", @@ -1658,17 +1745,9 @@ "isEnabled": 1 }, { - "name": "TimeSnapshot", + "name": "RetrieveLogsResponse", "code": 1, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "TimeSnapshotResponse", - "code": 2, - "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 @@ -1676,8 +1755,8 @@ ], "attributes": [ { - "name": "NetworkInterfaces", - "code": 0, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1687,32 +1766,16 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RebootCount", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "UpTime", - "code": 2, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", - "type": "int64u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1724,11 +1787,11 @@ "reportableChange": 0 }, { - "name": "TotalOperationalHours", - "code": 3, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int32u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -1740,40 +1803,76 @@ "reportableChange": 0 }, { - "name": "BootReason", - "code": 4, + "name": "FeatureMap", + "code": 65532, "mfgCode": null, "side": "server", - "type": "BootReasonEnum", + "type": "bitmap32", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "TestEventTriggersEnabled", - "code": 8, + "name": "ClusterRevision", + "code": 65533, "mfgCode": null, "side": "server", - "type": "boolean", + "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "false", + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, + } + ] + }, + { + "name": "General Diagnostics", + "code": 51, + "mfgCode": null, + "define": "GENERAL_DIAGNOSTICS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "TestEventTrigger", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshot", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TimeSnapshotResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "NetworkInterfaces", + "code": 0, "mfgCode": null, "side": "server", "type": "array", @@ -1783,13 +1882,93 @@ "bounded": 0, "defaultValue": null, "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "RebootCount", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "UpTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int64u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "TotalOperationalHours", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "BootReason", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "BootReasonEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TestEventTriggersEnabled", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "boolean", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "false", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", "type": "array", @@ -1804,8 +1983,8 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -1879,98 +2058,76 @@ ] }, { - "name": "Wi-Fi Network Diagnostics", - "code": 54, + "name": "Software Diagnostics", + "code": 52, "mfgCode": null, - "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", + "define": "SOFTWARE_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, + "commands": [ + { + "name": "ResetWatermarks", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { - "name": "BSSID", + "name": "ThreadMetrics", "code": 0, "mfgCode": null, "side": "server", - "type": "octet_string", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "SecurityType", + "name": "CurrentHeapFree", "code": 1, "mfgCode": null, "side": "server", - "type": "SecurityTypeEnum", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "WiFiVersion", + "name": "CurrentHeapUsed", "code": 2, "mfgCode": null, "side": "server", - "type": "WiFiVersionEnum", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "ChannelNumber", + "name": "CurrentHeapHighWatermark", "code": 3, "mfgCode": null, "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "RSSI", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "int8s", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "CurrentMaxRate", - "code": 11, - "mfgCode": null, - "side": "server", "type": "int64u", "included": 1, "storageOption": "External", @@ -1978,8 +2135,8 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { @@ -2014,22 +2171,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2053,10 +2194,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2074,232 +2215,196 @@ "bounded": 0, "defaultValue": "1", "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 } ] }, { - "name": "Administrator Commissioning", - "code": 60, + "name": "Wi-Fi Network Diagnostics", + "code": 54, "mfgCode": null, - "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", + "define": "WIFI_NETWORK_DIAGNOSTICS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "OpenCommissioningWindow", + "name": "ResetCounts", "code": 0, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, - { - "name": "RevokeCommissioning", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 } ], "attributes": [ { - "name": "WindowStatus", + "name": "BSSID", "code": 0, "mfgCode": null, "side": "server", - "type": "CommissioningWindowStatusEnum", + "type": "octet_string", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "AdminFabricIndex", + "name": "SecurityType", "code": 1, "mfgCode": null, "side": "server", - "type": "fabric_idx", + "type": "SecurityTypeEnum", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "AdminVendorId", + "name": "WiFiVersion", "code": 2, "mfgCode": null, "side": "server", - "type": "vendor_id", + "type": "WiFiVersionEnum", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "ChannelNumber", + "code": 3, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": null, "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "RSSI", + "code": 4, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "int8s", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 0, "maxInterval": 65344, "reportableChange": 0 - } - ] - }, - { - "name": "Operational Credentials", - "code": 62, - "mfgCode": null, - "define": "OPERATIONAL_CREDENTIALS_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "AttestationRequest", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AttestationResponse", - "code": 1, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "CertificateChainRequest", - "code": 2, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "CertificateChainResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "CSRRequest", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 }, { - "name": "CSRResponse", + "name": "BeaconLostCount", "code": 5, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "AddNOC", + "name": "BeaconRxCount", "code": 6, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "UpdateNOC", + "name": "PacketMulticastRxCount", "code": 7, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "NOCResponse", + "name": "PacketMulticastTxCount", "code": 8, "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "UpdateFabricLabel", + "name": "PacketUnicastRxCount", "code": 9, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 }, { - "name": "RemoveFabric", + "name": "PacketUnicastTxCount", "code": 10, "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "AddTrustedRootCertificate", - "code": 11, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "NOCs", - "code": 0, - "mfgCode": null, "side": "server", - "type": "array", + "type": "int32u", "included": 1, "storageOption": "External", "singleton": 0, @@ -2311,11 +2416,11 @@ "reportableChange": 0 }, { - "name": "Fabrics", - "code": 1, + "name": "CurrentMaxRate", + "code": 11, "mfgCode": null, "side": "server", - "type": "array", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, @@ -2327,40 +2432,40 @@ "reportableChange": 0 }, { - "name": "SupportedFabrics", - "code": 2, + "name": "OverrunCount", + "code": 12, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "int64u", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CommissionedFabrics", - "code": 3, + "name": "GeneratedCommandList", + "code": 65528, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "TrustedRootCertificates", - "code": 4, + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -2370,16 +2475,16 @@ "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, + "minInterval": 1, + "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CurrentFabricIndex", - "code": 5, + "name": "AttributeList", + "code": 65531, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, "storageOption": "External", "singleton": 0, @@ -2400,7 +2505,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2422,18 +2527,41 @@ "maxInterval": 65344, "reportableChange": 0 } + ], + "events": [ + { + "name": "Disconnection", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "AssociationFailure", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ConnectionStatus", + "code": 2, + "mfgCode": null, + "side": "server", + "included": 1 + } ] }, { - "name": "Group Key Management", - "code": 63, + "name": "Administrator Commissioning", + "code": 60, "mfgCode": null, - "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "define": "ADMINISTRATOR_COMMISSIONING_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "KeySetWrite", + "name": "OpenCommissioningWindow", "code": 0, "mfgCode": null, "source": "client", @@ -2441,101 +2569,21 @@ "isEnabled": 1 }, { - "name": "KeySetRead", - "code": 1, + "name": "RevokeCommissioning", + "code": 2, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 - }, + } + ], + "attributes": [ { - "name": "KeySetReadResponse", - "code": 2, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "KeySetRemove", - "code": 3, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "KeySetReadAllIndices", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "KeySetReadAllIndicesResponse", - "code": 5, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "GroupKeyMap", + "name": "WindowStatus", "code": 0, "mfgCode": null, "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "GroupTable", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - }, - { - "name": "MaxGroupsPerFabric", - "code": 2, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "MaxGroupKeysPerFabric", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "int16u", + "type": "CommissioningWindowStatusEnum", "included": 1, "storageOption": "External", "singleton": 0, @@ -2547,11 +2595,11 @@ "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "AdminFabricIndex", + "code": 1, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "fabric_idx", "included": 1, "storageOption": "External", "singleton": 0, @@ -2563,106 +2611,17 @@ "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "AdminVendorId", + "code": 2, "mfgCode": null, "side": "server", - "type": "int16u", + "type": "vendor_id", "included": 1, "storageOption": "External", "singleton": 0, "bounded": 0, "defaultValue": null, "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - } - ] - }, - { - "id": 2, - "name": "Anonymous Endpoint Type", - "deviceTypeRef": { - "code": 115, - "profileId": 259, - "label": "MA-laundry-washer", - "name": "MA-laundry-washer" - }, - "deviceTypes": [ - { - "code": 115, - "profileId": 259, - "label": "MA-laundry-washer", - "name": "MA-laundry-washer" - } - ], - "deviceVersions": [ - 1 - ], - "deviceIdentifiers": [ - 115 - ], - "deviceTypeName": "MA-laundry-washer", - "deviceTypeCode": 115, - "deviceTypeProfileId": 259, - "clusters": [ - { - "name": "Identify", - "code": 3, - "mfgCode": null, - "define": "IDENTIFY_CLUSTER", - "side": "server", - "enabled": 1, - "commands": [ - { - "name": "Identify", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - }, - { - "name": "TriggerEffect", - "code": 64, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "IdentifyTime", - "code": 0, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "IdentifyType", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "IdentifyTypeEnum", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0x00", - "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2699,22 +2658,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -2757,24 +2700,24 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "4", + "defaultValue": "1", "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, + "minInterval": 0, + "maxInterval": 65344, "reportableChange": 0 } ] }, { - "name": "Groups", - "code": 4, + "name": "Operational Credentials", + "code": 62, "mfgCode": null, - "define": "GROUPS_CLUSTER", + "define": "OPERATIONAL_CREDENTIALS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "AddGroup", + "name": "AttestationRequest", "code": 0, "mfgCode": null, "source": "client", @@ -2782,73 +2725,89 @@ "isEnabled": 1 }, { - "name": "AddGroupResponse", - "code": 0, + "name": "AttestationResponse", + "code": 1, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "ViewGroup", - "code": 1, + "name": "CertificateChainRequest", + "code": 2, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "ViewGroupResponse", - "code": 1, + "name": "CertificateChainResponse", + "code": 3, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "GetGroupMembership", - "code": 2, + "name": "CSRRequest", + "code": 4, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "GetGroupMembershipResponse", - "code": 2, + "name": "CSRResponse", + "code": 5, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "RemoveGroup", - "code": 3, + "name": "AddNOC", + "code": 6, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "RemoveGroupResponse", - "code": 3, + "name": "UpdateNOC", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "NOCResponse", + "code": 8, "mfgCode": null, "source": "server", "isIncoming": 0, "isEnabled": 1 }, { - "name": "RemoveAllGroups", - "code": 4, + "name": "UpdateFabricLabel", + "code": 9, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "AddGroupIfIdentifying", - "code": 5, - "mfgCode": null, + "name": "RemoveFabric", + "code": 10, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "AddTrustedRootCertificate", + "code": 11, + "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 @@ -2856,16 +2815,300 @@ ], "attributes": [ { - "name": "NameSupport", + "name": "NOCs", "code": 0, "mfgCode": null, "side": "server", - "type": "NameSupportBitmap", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Fabrics", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "SupportedFabrics", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CommissionedFabrics", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "TrustedRootCertificates", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentFabricIndex", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, + { + "name": "Group Key Management", + "code": 63, + "mfgCode": null, + "define": "GROUP_KEY_MANAGEMENT_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "KeySetWrite", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetRead", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "KeySetRemove", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndices", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "KeySetReadAllIndicesResponse", + "code": 5, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "GroupKeyMap", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GroupTable", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "MaxGroupsPerFabric", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "MaxGroupKeysPerFabric", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -2904,8 +3147,163 @@ "reportableChange": 0 }, { - "name": "EventList", - "code": 65530, + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + } + ] + }, + { + "id": 2, + "name": "Anonymous Endpoint Type", + "deviceTypeRef": { + "code": 115, + "profileId": 259, + "label": "MA-laundry-washer", + "name": "MA-laundry-washer", + "deviceTypeOrder": 0 + }, + "deviceTypes": [ + { + "code": 115, + "profileId": 259, + "label": "MA-laundry-washer", + "name": "MA-laundry-washer", + "deviceTypeOrder": 0 + } + ], + "deviceVersions": [ + 1 + ], + "deviceIdentifiers": [ + 115 + ], + "deviceTypeName": "MA-laundry-washer", + "deviceTypeCode": 115, + "deviceTypeProfileId": 259, + "clusters": [ + { + "name": "Identify", + "code": 3, + "mfgCode": null, + "define": "IDENTIFY_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "Identify", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "TriggerEffect", + "code": 64, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "IdentifyTime", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "IdentifyType", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "IdentifyTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0x00", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, "mfgCode": null, "side": "server", "type": "array", @@ -2970,15 +3368,15 @@ ] }, { - "name": "On/Off", - "code": 6, + "name": "Groups", + "code": 4, "mfgCode": null, - "define": "ON_OFF_CLUSTER", + "define": "GROUPS_CLUSTER", "side": "server", "enabled": 1, "commands": [ { - "name": "Off", + "name": "AddGroup", "code": 0, "mfgCode": null, "source": "client", @@ -2986,7 +3384,15 @@ "isEnabled": 1 }, { - "name": "On", + "name": "AddGroupResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "ViewGroup", "code": 1, "mfgCode": null, "source": "client", @@ -2994,7 +3400,15 @@ "isEnabled": 1 }, { - "name": "Toggle", + "name": "ViewGroupResponse", + "code": 1, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "GetGroupMembership", "code": 2, "mfgCode": null, "source": "client", @@ -3002,24 +3416,40 @@ "isEnabled": 1 }, { - "name": "OffWithEffect", - "code": 64, + "name": "GetGroupMembershipResponse", + "code": 2, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveGroup", + "code": 3, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "OnWithRecallGlobalScene", - "code": 65, + "name": "RemoveGroupResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "RemoveAllGroups", + "code": 4, "mfgCode": null, "source": "client", "isIncoming": 1, "isEnabled": 1 }, { - "name": "OnWithTimedOff", - "code": 66, + "name": "AddGroupIfIdentifying", + "code": 5, "mfgCode": null, "source": "client", "isIncoming": 1, @@ -3028,80 +3458,16 @@ ], "attributes": [ { - "name": "OnOff", + "name": "NameSupport", "code": 0, "mfgCode": null, "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "NVM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GlobalSceneControl", - "code": 16384, - "mfgCode": null, - "side": "server", - "type": "boolean", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "1", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "OnTime", - "code": 16385, - "mfgCode": null, - "side": "server", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "OffWaitTime", - "code": 16386, - "mfgCode": null, - "side": "server", - "type": "int16u", + "type": "NameSupportBitmap", "included": 1, "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StartUpOnOff", - "code": 16387, - "mfgCode": null, - "side": "server", - "type": "StartUpOnOffEnum", - "included": 1, - "storageOption": "NVM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0xFF", + "defaultValue": "", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3139,22 +3505,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3181,7 +3531,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3197,7 +3547,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "5", + "defaultValue": "4", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3206,194 +3556,138 @@ ] }, { - "name": "Descriptor", - "code": 29, + "name": "On/Off", + "code": 6, "mfgCode": null, - "define": "DESCRIPTOR_CLUSTER", + "define": "ON_OFF_CLUSTER", "side": "server", "enabled": 1, - "attributes": [ + "commands": [ { - "name": "DeviceTypeList", + "name": "Off", "code": 0, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "ServerList", + "name": "On", "code": 1, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "ClientList", + "name": "Toggle", "code": 2, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "PartsList", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "GeneratedCommandList", - "code": 65528, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "AcceptedCommandList", - "code": 65529, + "name": "OffWithEffect", + "code": 64, "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 + "source": "client", + "isIncoming": 1, + "isEnabled": 1 }, { - "name": "EventList", - "code": 65530, + "name": "OnWithRecallGlobalScene", + "code": 65, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "OnWithTimedOff", + "code": 66, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "OnOff", + "code": 0, "mfgCode": null, "side": "server", - "type": "array", + "type": "boolean", "included": 1, - "storageOption": "External", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "AttributeList", - "code": 65531, + "name": "GlobalSceneControl", + "code": 16384, "mfgCode": null, "side": "server", - "type": "array", + "type": "boolean", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "1", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "FeatureMap", - "code": 65532, + "name": "OnTime", + "code": 16385, "mfgCode": null, "side": "server", - "type": "bitmap32", + "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "ClusterRevision", - "code": 65533, + "name": "OffWaitTime", + "code": 16386, "mfgCode": null, "side": "server", "type": "int16u", "included": 1, - "storageOption": "External", + "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 - } - ] - }, - { - "name": "Binding", - "code": 30, - "mfgCode": null, - "define": "BINDING_CLUSTER", - "side": "server", - "enabled": 1, - "attributes": [ + }, { - "name": "Binding", - "code": 0, + "name": "StartUpOnOff", + "code": 16387, "mfgCode": null, "side": "server", - "type": "array", + "type": "StartUpOnOffEnum", "included": 1, - "storageOption": "External", + "storageOption": "NVM", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0xFF", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3431,22 +3725,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "EventList", - "code": 65530, - "mfgCode": null, - "side": "server", - "type": "array", - "included": 1, - "storageOption": "External", - "singleton": 0, - "bounded": 0, - "defaultValue": null, - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "AttributeList", "code": 65531, @@ -3473,7 +3751,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "0", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3489,7 +3767,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "6", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3498,80 +3776,64 @@ ] }, { - "name": "Power Source", - "code": 47, + "name": "Descriptor", + "code": 29, "mfgCode": null, - "define": "POWER_SOURCE_CLUSTER", + "define": "DESCRIPTOR_CLUSTER", "side": "server", "enabled": 1, "attributes": [ { - "name": "Status", + "name": "DeviceTypeList", "code": 0, "mfgCode": null, "side": "server", - "type": "PowerSourceStatusEnum", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "Order", + "name": "ServerList", "code": 1, "mfgCode": null, "side": "server", - "type": "int8u", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "Description", + "name": "ClientList", "code": 2, "mfgCode": null, "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "WiredCurrentType", - "code": 5, - "mfgCode": null, - "side": "server", - "type": "WiredCurrentTypeEnum", + "type": "array", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "EndpointList", - "code": 31, + "name": "PartsList", + "code": 3, "mfgCode": null, "side": "server", "type": "array", @@ -3656,10 +3918,10 @@ "side": "server", "type": "bitmap32", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3672,10 +3934,10 @@ "side": "server", "type": "int16u", "included": 1, - "storageOption": "RAM", + "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -3684,15 +3946,15 @@ ] }, { - "name": "Fixed Label", - "code": 64, + "name": "Binding", + "code": 30, "mfgCode": null, - "define": "FIXED_LABEL_CLUSTER", + "define": "BINDING_CLUSTER", "side": "server", "enabled": 1, "attributes": [ { - "name": "LabelList", + "name": "Binding", "code": 0, "mfgCode": null, "side": "server", @@ -3806,10 +4068,10 @@ ] }, { - "name": "User Label", - "code": 65, + "name": "Fixed Label", + "code": 64, "mfgCode": null, - "define": "USER_LABEL_CLUSTER", + "define": "FIXED_LABEL_CLUSTER", "side": "server", "enabled": 1, "attributes": [ @@ -3928,60 +4190,18 @@ ] }, { - "name": "Mode Select", - "code": 80, + "name": "User Label", + "code": 65, "mfgCode": null, - "define": "MODE_SELECT_CLUSTER", + "define": "USER_LABEL_CLUSTER", "side": "server", "enabled": 1, - "commands": [ - { - "name": "ChangeToMode", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 1, - "isEnabled": 1 - } - ], "attributes": [ { - "name": "Description", + "name": "LabelList", "code": 0, "mfgCode": null, "side": "server", - "type": "char_string", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StandardNamespace", - "code": 1, - "mfgCode": null, - "side": "server", - "type": "enum16", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "SupportedModes", - "code": 2, - "mfgCode": null, - "side": "server", "type": "array", "included": 1, "storageOption": "External", @@ -3993,54 +4213,6 @@ "maxInterval": 65534, "reportableChange": 0 }, - { - "name": "CurrentMode", - "code": 3, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "StartUpMode", - "code": 4, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "OnMode", - "code": 5, - "mfgCode": null, - "side": "server", - "type": "int8u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, { "name": "GeneratedCommandList", "code": 65528, @@ -4319,7 +4491,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4881,7 +5053,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "1", + "defaultValue": "2", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -4926,4 +5098,4 @@ "parentEndpointIdentifier": null } ] -} \ No newline at end of file +} diff --git a/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt b/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt index 9103b6a556..b3a03be040 100644 --- a/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt +++ b/examples/laundry-washer-app/nxp/zephyr/CMakeLists.txt @@ -106,10 +106,9 @@ target_sources(app PRIVATE ${ALL_CLUSTERS_COMMON_DIR}/src/smco-stub.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/bridged-actions-stub.cpp - ${ALL_CLUSTERS_COMMON_DIR}/src/static-supported-modes-manager.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/static-supported-temperature-levels.cpp - ${ALL_CLUSTERS_COMMON_DIR}/src/laundry-washer-mode.cpp + ${LAUNDRY_WASHER_NXP_COMMON_DIR}/main/laundry-washer-mode.cpp ${ALL_CLUSTERS_COMMON_DIR}/src/laundry-washer-controls-delegate-impl.cpp - ${LAUNDRY_WASHER_NXP_COMMON_DIR}/main/operational-state-delegate-impl.cpp + ${ALL_CLUSTERS_COMMON_DIR}/src/operational-state-delegate-impl.cpp ${EXAMPLE_PLATFORM_NXP_COMMON_DIR}/icd/source/ICDUtil.cpp ) From fb24b9035d861716942139046e377749494e72d1 Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Fri, 29 Nov 2024 16:57:35 +0800 Subject: [PATCH 118/219] Decouple ember-specific functions from descriptor cluster (#36493) * descriptor: decouple from ember * Restyled by clang-format * fix shadow error * fix test build * fix test build * use Client cluster iteration * Restyled by clang-format * fix CI building error * fix android build * review changes * Restyled by clang-format * review changes * some doc changes * Fix the semantic tags iterator and add unit tests for the new functions * Restyled by clang-format * fix clang tidy check * add composition test * Restyled by clang-format * Update src/app/data-model-provider/MetadataTypes.h Co-authored-by: Boris Zbarsky * Update src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp Co-authored-by: Boris Zbarsky --------- Co-authored-by: Restyled.io Co-authored-by: Andrei Litvin Co-authored-by: Boris Zbarsky --- .../common/pigweed/rpc_services/Attributes.h | 2 +- src/app/AttributePathExpandIterator.cpp | 14 +- src/app/InteractionModelEngine.cpp | 16 +- src/app/clusters/descriptor/descriptor.cpp | 109 +++---- .../CodegenDataModelProvider.cpp | 242 ++++++++++++--- .../CodegenDataModelProvider.h | 37 ++- .../CodegenDataModelProvider_Write.cpp | 2 +- .../tests/TestCodegenModelViaMocks.cpp | 287 +++++++++++++++--- src/app/data-model-provider/MetadataTypes.cpp | 6 +- src/app/data-model-provider/MetadataTypes.h | 59 +++- src/app/dynamic_server/DynamicDispatcher.cpp | 23 ++ src/app/reporting/Engine.cpp | 6 +- src/app/tests/test-interaction-model-api.cpp | 42 ++- src/app/tests/test-interaction-model-api.h | 15 +- src/app/util/af-types.h | 2 + src/app/util/attribute-storage.cpp | 14 + src/app/util/attribute-storage.h | 12 + src/app/util/mock/MockNodeConfig.cpp | 22 +- src/app/util/mock/MockNodeConfig.h | 21 +- src/app/util/mock/attribute-storage.cpp | 33 ++ .../tests/data_model/DataModelFixtures.cpp | 42 ++- .../tests/data_model/DataModelFixtures.h | 15 +- 22 files changed, 802 insertions(+), 219 deletions(-) diff --git a/examples/common/pigweed/rpc_services/Attributes.h b/examples/common/pigweed/rpc_services/Attributes.h index 99e348e3a2..261831ba9b 100644 --- a/examples/common/pigweed/rpc_services/Attributes.h +++ b/examples/common/pigweed/rpc_services/Attributes.h @@ -221,7 +221,7 @@ class Attributes : public pw_rpc::nanopb::Attributes::Service request.operationFlags.Set(app::DataModel::OperationFlags::kInternal); request.subjectDescriptor = &subjectDescriptor; - std::optional info = provider->GetClusterInfo(path); + std::optional info = provider->GetServerClusterInfo(path); if (!info.has_value()) { return ::pw::Status::NotFound(); diff --git a/src/app/AttributePathExpandIterator.cpp b/src/app/AttributePathExpandIterator.cpp index 96aa277291..419067db9d 100644 --- a/src/app/AttributePathExpandIterator.cpp +++ b/src/app/AttributePathExpandIterator.cpp @@ -115,13 +115,13 @@ std::optional AttributePathExpandIterator::NextClusterId() { if (mpAttributePath->mValue.HasWildcardClusterId()) { - ClusterEntry entry = mDataModelProvider->FirstCluster(mOutputPath.mEndpointId); + ClusterEntry entry = mDataModelProvider->FirstServerCluster(mOutputPath.mEndpointId); return entry.IsValid() ? std::make_optional(entry.path.mClusterId) : std::nullopt; } // only return a cluster if it is valid const ConcreteClusterPath clusterPath(mOutputPath.mEndpointId, mpAttributePath->mValue.mClusterId); - if (!mDataModelProvider->GetClusterInfo(clusterPath).has_value()) + if (!mDataModelProvider->GetServerClusterInfo(clusterPath).has_value()) { return std::nullopt; } @@ -131,7 +131,7 @@ std::optional AttributePathExpandIterator::NextClusterId() VerifyOrReturnValue(mpAttributePath->mValue.HasWildcardClusterId(), std::nullopt); - ClusterEntry entry = mDataModelProvider->NextCluster(mOutputPath); + ClusterEntry entry = mDataModelProvider->NextServerCluster(mOutputPath); return entry.IsValid() ? std::make_optional(entry.path.mClusterId) : std::nullopt; } @@ -141,8 +141,8 @@ std::optional AttributePathExpandIterator::NextEndpointId() { if (mpAttributePath->mValue.HasWildcardEndpointId()) { - EndpointId id = mDataModelProvider->FirstEndpoint(); - return (id != kInvalidEndpointId) ? std::make_optional(id) : std::nullopt; + EndpointEntry ep = mDataModelProvider->FirstEndpoint(); + return (ep.id != kInvalidEndpointId) ? std::make_optional(ep.id) : std::nullopt; } return mpAttributePath->mValue.mEndpointId; @@ -150,8 +150,8 @@ std::optional AttributePathExpandIterator::NextEndpointId() VerifyOrReturnValue(mpAttributePath->mValue.HasWildcardEndpointId(), std::nullopt); - EndpointId id = mDataModelProvider->NextEndpoint(mOutputPath.mEndpointId); - return (id != kInvalidEndpointId) ? std::make_optional(id) : std::nullopt; + EndpointEntry ep = mDataModelProvider->NextEndpoint(mOutputPath.mEndpointId); + return (ep.id != kInvalidEndpointId) ? std::make_optional(ep.id) : std::nullopt; } void AttributePathExpandIterator::ResetCurrentCluster() diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 56acd09661..78967c6d53 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -89,14 +89,14 @@ bool MayHaveAccessibleEventPathForEndpoint(DataModel::Provider * aProvider, Endp aSubjectDescriptor); } - DataModel::ClusterEntry clusterEntry = aProvider->FirstCluster(aEventPath.mEndpointId); + DataModel::ClusterEntry clusterEntry = aProvider->FirstServerCluster(aEventPath.mEndpointId); while (clusterEntry.IsValid()) { if (MayHaveAccessibleEventPathForEndpointAndCluster(clusterEntry.path, aEventPath, aSubjectDescriptor)) { return true; } - clusterEntry = aProvider->NextCluster(clusterEntry.path); + clusterEntry = aProvider->NextServerCluster(clusterEntry.path); } return false; @@ -112,10 +112,9 @@ bool MayHaveAccessibleEventPath(DataModel::Provider * aProvider, const EventPath return MayHaveAccessibleEventPathForEndpoint(aProvider, aEventPath.mEndpointId, aEventPath, subjectDescriptor); } - for (EndpointId endpointId = aProvider->FirstEndpoint(); endpointId != kInvalidEndpointId; - endpointId = aProvider->NextEndpoint(endpointId)) + for (DataModel::EndpointEntry ep = aProvider->FirstEndpoint(); ep.IsValid(); ep = aProvider->NextEndpoint(ep.id)) { - if (MayHaveAccessibleEventPathForEndpoint(aProvider, endpointId, aEventPath, subjectDescriptor)) + if (MayHaveAccessibleEventPathForEndpoint(aProvider, ep.id, aEventPath, subjectDescriptor)) { return true; } @@ -1793,17 +1792,16 @@ Protocols::InteractionModel::Status InteractionModelEngine::CheckCommandExistenc // We failed, figure out why ... // - if (provider->GetClusterInfo(aCommandPath).has_value()) + if (provider->GetServerClusterInfo(aCommandPath).has_value()) { return Protocols::InteractionModel::Status::UnsupportedCommand; // cluster exists, so command is invalid } // At this point either cluster or endpoint does not exist. If we find the endpoint, then the cluster // is invalid - for (EndpointId endpoint = provider->FirstEndpoint(); endpoint != kInvalidEndpointId; - endpoint = provider->NextEndpoint(endpoint)) + for (DataModel::EndpointEntry ep = provider->FirstEndpoint(); ep.IsValid(); ep = provider->NextEndpoint(ep.id)) { - if (endpoint == aCommandPath.mEndpointId) + if (ep.id == aCommandPath.mEndpointId) { // endpoint exists, so cluster is invalid return Protocols::InteractionModel::Status::UnsupportedCluster; diff --git a/src/app/clusters/descriptor/descriptor.cpp b/src/app/clusters/descriptor/descriptor.cpp index a8e5038764..409240e66a 100644 --- a/src/app/clusters/descriptor/descriptor.cpp +++ b/src/app/clusters/descriptor/descriptor.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -73,19 +75,13 @@ CHIP_ERROR DescriptorAttrAccess::ReadFeatureMap(EndpointId endpoint, AttributeVa CHIP_ERROR DescriptorAttrAccess::ReadTagListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder) { return aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { - Clusters::Descriptor::Structs::SemanticTagStruct::Type tag; - size_t index = 0; - CHIP_ERROR err = CHIP_NO_ERROR; - while ((err = GetSemanticTagForEndpointAtIndex(endpoint, index, tag)) == CHIP_NO_ERROR) + auto tag = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetFirstSemanticTag(endpoint); + while (tag.has_value()) { - ReturnErrorOnFailure(encoder.Encode(tag)); - index++; + ReturnErrorOnFailure(encoder.Encode(tag.value())); + tag = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetNextSemanticTag(endpoint, tag.value()); } - if (err == CHIP_ERROR_NOT_FOUND) - { - return CHIP_NO_ERROR; - } - return err; + return CHIP_NO_ERROR; }); } @@ -93,67 +89,63 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu { CHIP_ERROR err = CHIP_NO_ERROR; + auto endpointInfo = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetEndpointInfo(endpoint); if (endpoint == 0x00) { err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR { - for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); + while (endpointEntry.IsValid()) { - if (emberAfEndpointIndexIsEnabled(index)) + if (endpointEntry.id != 0) { - EndpointId endpointId = emberAfEndpointFromIndex(index); - if (endpointId == 0) - continue; - - ReturnErrorOnFailure(encoder.Encode(endpointId)); + ReturnErrorOnFailure(encoder.Encode(endpointEntry.id)); } + endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id); } - return CHIP_NO_ERROR; }); } - else if (IsFlatCompositionForEndpoint(endpoint)) + else if (endpointInfo.has_value() && + endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamilyPattern) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { - for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); + while (endpointEntry.IsValid()) { - if (!emberAfEndpointIndexIsEnabled(index)) - continue; - - uint16_t childIndex = index; - while (childIndex != chip::kInvalidListIndex) + EndpointId parentEndpointId = endpointEntry.info.parentId; + while (parentEndpointId != chip::kInvalidEndpointId) { - EndpointId parentEndpointId = emberAfParentEndpointFromIndex(childIndex); - if (parentEndpointId == chip::kInvalidEndpointId) - break; - if (parentEndpointId == endpoint) { - ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index))); + ReturnErrorOnFailure(encoder.Encode(endpointEntry.id)); break; } - - childIndex = emberAfIndexFromEndpoint(parentEndpointId); + auto parentEndpointInfo = + InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetEndpointInfo(parentEndpointId); + if (!parentEndpointInfo.has_value()) + { + break; + } + parentEndpointId = parentEndpointInfo->parentId; } + endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id); } return CHIP_NO_ERROR; }); } - else if (IsTreeCompositionForEndpoint(endpoint)) + else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTreePattern) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { - for (uint16_t index = 0; index < emberAfEndpointCount(); index++) + auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); + while (endpointEntry.IsValid()) { - if (!emberAfEndpointIndexIsEnabled(index)) - continue; - - EndpointId parentEndpointId = emberAfParentEndpointFromIndex(index); - if (parentEndpointId == endpoint) + if (endpointEntry.info.parentId == endpoint) { - ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index))); + ReturnErrorOnFailure(encoder.Encode(endpointEntry.id)); } + endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id); } - return CHIP_NO_ERROR; }); } @@ -165,16 +157,15 @@ CHIP_ERROR DescriptorAttrAccess::ReadDeviceAttribute(EndpointId endpoint, Attrib { CHIP_ERROR err = aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR { Descriptor::Structs::DeviceTypeStruct::Type deviceStruct; - CHIP_ERROR err2; - auto deviceTypeList = emberAfDeviceTypeListFromEndpoint(endpoint, err2); - ReturnErrorOnFailure(err2); + auto deviceType = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstDeviceType(endpoint); - for (auto & deviceType : deviceTypeList) + while (deviceType.has_value()) { - deviceStruct.deviceType = deviceType.deviceId; - deviceStruct.revision = deviceType.deviceVersion; + deviceStruct.deviceType = deviceType->deviceTypeId; + deviceStruct.revision = deviceType->deviceTypeRevision; ReturnErrorOnFailure(encoder.Encode(deviceStruct)); + deviceType = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextDeviceType(endpoint, *deviceType); } return CHIP_NO_ERROR; @@ -186,12 +177,24 @@ CHIP_ERROR DescriptorAttrAccess::ReadDeviceAttribute(EndpointId endpoint, Attrib CHIP_ERROR DescriptorAttrAccess::ReadClientServerAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder, bool server) { CHIP_ERROR err = aEncoder.EncodeList([&endpoint, server](const auto & encoder) -> CHIP_ERROR { - uint8_t clusterCount = emberAfClusterCount(endpoint, server); - - for (uint8_t clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++) + if (server) { - const EmberAfCluster * cluster = emberAfGetNthCluster(endpoint, clusterIndex, server); - ReturnErrorOnFailure(encoder.Encode(cluster->clusterId)); + auto clusterEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstServerCluster(endpoint); + while (clusterEntry.IsValid()) + { + ReturnErrorOnFailure(encoder.Encode(clusterEntry.path.mClusterId)); + clusterEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextServerCluster(clusterEntry.path); + } + } + else + { + ConcreteClusterPath clusterPath = + InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstClientCluster(endpoint); + while (clusterPath.HasValidIds()) + { + ReturnErrorOnFailure(encoder.Encode(clusterPath.mClusterId)); + clusterPath = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextClientCluster(clusterPath); + } } return CHIP_NO_ERROR; diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index b0815da48e..4eae3de1e2 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -128,10 +128,8 @@ std::variant LoadClusterInfo(const ConcreteC } DataModel::ClusterInfo info(*versionPtr); - // TODO: set entry flags: // info->flags.Set(ClusterQualityFlags::kDiagnosticsData) - return info; } @@ -194,6 +192,23 @@ DataModel::ClusterEntry FirstServerClusterEntry(EndpointId endpointId, const Emb return DataModel::ClusterEntry::kInvalid; } +ClusterId FirstClientClusterId(const EmberAfEndpointType * endpoint, unsigned start_index, unsigned & found_index) +{ + for (unsigned cluster_idx = start_index; cluster_idx < endpoint->clusterCount; cluster_idx++) + { + const EmberAfCluster & cluster = endpoint->cluster[cluster_idx]; + if (!cluster.IsClient()) + { + continue; + } + + found_index = cluster_idx; + return cluster.clusterId; + } + + return kInvalidClusterId; +} + /// Load the attribute information into the specified destination /// /// `info` is assumed to be default-constructed/clear (i.e. this sets flags, but does not reset them). @@ -255,8 +270,8 @@ DataModel::DeviceTypeEntry DeviceTypeEntryFromEmber(const EmberAfDeviceType & ot { DataModel::DeviceTypeEntry entry; - entry.deviceTypeId = other.deviceId; - entry.deviceTypeVersion = other.deviceVersion; + entry.deviceTypeId = other.deviceId; + entry.deviceTypeRevision = other.deviceVersion; return entry; } @@ -265,7 +280,7 @@ DataModel::DeviceTypeEntry DeviceTypeEntryFromEmber(const EmberAfDeviceType & ot // so you must do `a == b` and the `b == a` will not work. bool operator==(const DataModel::DeviceTypeEntry & a, const EmberAfDeviceType & b) { - return (a.deviceTypeId == b.deviceId) && (a.deviceTypeVersion == b.deviceVersion); + return (a.deviceTypeId == b.deviceId) && (a.deviceTypeRevision == b.deviceVersion); } /// Find the `index` where one of the following holds: @@ -300,6 +315,96 @@ unsigned FindNextDeviceTypeIndex(Span types, const Data const ConcreteCommandPath kInvalidCommandPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId); +std::optional GetEndpointInfoAtIndex(uint16_t endpointIndex) +{ + VerifyOrReturnValue(emberAfEndpointIndexIsEnabled(endpointIndex), std::nullopt); + EndpointId parent = emberAfParentEndpointFromIndex(endpointIndex); + if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kFullFamily) + { + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kFullFamilyPattern); + } + if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kTree) + { + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kTreePattern); + } + return std::nullopt; +} + +DataModel::EndpointEntry FirstEndpointEntry(unsigned start_index, uint16_t & found_index) +{ + // find the first enabled index after the start index + const uint16_t lastEndpointIndex = emberAfEndpointCount(); + for (uint16_t endpoint_idx = static_cast(start_index); endpoint_idx < lastEndpointIndex; endpoint_idx++) + { + if (emberAfEndpointIndexIsEnabled(endpoint_idx)) + { + found_index = endpoint_idx; + DataModel::EndpointEntry endpointEntry = DataModel::EndpointEntry::kInvalid; + endpointEntry.id = emberAfEndpointFromIndex(endpoint_idx); + auto endpointInfo = GetEndpointInfoAtIndex(endpoint_idx); + // The endpoint info should have value as this endpoint should be valid at this time + VerifyOrDie(endpointInfo.has_value()); + endpointEntry.info = endpointInfo.value(); + return endpointEntry; + } + } + + // No enabled endpoint found. Give up + return DataModel::EndpointEntry::kInvalid; +} + +bool operator==(const DataModel::Provider::SemanticTag & tagA, const DataModel::Provider::SemanticTag & tagB) +{ + // Label is an optional and nullable value of CharSpan. Optional and Nullable have overload for ==, + // But `==` is deleted for CharSpan. Here we only check whether the string is the same. + if (tagA.label.HasValue() != tagB.label.HasValue()) + { + return false; + } + if (tagA.label.HasValue()) + { + if (tagA.label.Value().IsNull() != tagB.label.Value().IsNull()) + { + return false; + } + if (!tagA.label.Value().IsNull()) + { + if (!tagA.label.Value().Value().data_equal(tagB.label.Value().Value())) + { + return false; + } + } + } + return (tagA.tag == tagB.tag) && (tagA.mfgCode == tagB.mfgCode) && (tagA.namespaceID == tagB.namespaceID); +} + +std::optional FindNextSemanticTagIndex(EndpointId endpoint, const DataModel::Provider::SemanticTag & previous, + unsigned hintWherePreviousMayBe) +{ + DataModel::Provider::SemanticTag hintTag; + // Check whether the hint is the previous tag + if (GetSemanticTagForEndpointAtIndex(endpoint, hintWherePreviousMayBe, hintTag) == CHIP_NO_ERROR) + { + if (previous == hintTag) + { + return std::make_optional(hintWherePreviousMayBe + 1); + } + } + // If the hint is not the previous tag, iterate over all the tags to find the index for the previous tag + unsigned index = 0; + // Ensure that the next index is in the range + while (GetSemanticTagForEndpointAtIndex(endpoint, index + 1, hintTag) == CHIP_NO_ERROR && + GetSemanticTagForEndpointAtIndex(endpoint, index, hintTag) == CHIP_NO_ERROR) + { + if (previous == hintTag) + { + return std::make_optional(index + 1); + } + index++; + } + return std::nullopt; +} + } // namespace std::optional CodegenDataModelProvider::EmberCommandListIterator::First(const CommandId * list) @@ -397,21 +502,19 @@ bool CodegenDataModelProvider::EndpointExists(EndpointId endpoint) return (emberAfIndexFromEndpoint(endpoint) != kEmberInvalidEndpointIndex); } -EndpointId CodegenDataModelProvider::FirstEndpoint() +std::optional CodegenDataModelProvider::GetEndpointInfo(EndpointId endpoint) { - // find the first enabled index - const uint16_t lastEndpointIndex = emberAfEndpointCount(); - for (uint16_t endpoint_idx = 0; endpoint_idx < lastEndpointIndex; endpoint_idx++) + std::optional endpoint_idx = TryFindEndpointIndex(endpoint); + if (endpoint_idx.has_value()) { - if (emberAfEndpointIndexIsEnabled(endpoint_idx)) - { - mEndpointIterationHint = endpoint_idx; - return emberAfEndpointFromIndex(endpoint_idx); - } + return GetEndpointInfoAtIndex(static_cast(*endpoint_idx)); } + return std::nullopt; +} - // No enabled endpoint found. Give up - return kInvalidEndpointId; +DataModel::EndpointEntry CodegenDataModelProvider::FirstEndpoint() +{ + return FirstEndpointEntry(0, mEndpointIterationHint); } std::optional CodegenDataModelProvider::TryFindEndpointIndex(EndpointId id) const @@ -434,51 +537,41 @@ std::optional CodegenDataModelProvider::TryFindEndpointIndex(EndpointI return std::make_optional(idx); } -EndpointId CodegenDataModelProvider::NextEndpoint(EndpointId before) +DataModel::EndpointEntry CodegenDataModelProvider::NextEndpoint(EndpointId before) { - const uint16_t lastEndpointIndex = emberAfEndpointCount(); - std::optional before_idx = TryFindEndpointIndex(before); if (!before_idx.has_value()) { - return kInvalidEndpointId; + return DataModel::EndpointEntry::kInvalid; } - - // find the first enabled index - for (uint16_t endpoint_idx = static_cast(*before_idx + 1); endpoint_idx < lastEndpointIndex; endpoint_idx++) - { - if (emberAfEndpointIndexIsEnabled(endpoint_idx)) - { - mEndpointIterationHint = endpoint_idx; - return emberAfEndpointFromIndex(endpoint_idx); - } - } - - // No enabled enpoint after "before" was found, give up - return kInvalidEndpointId; + return FirstEndpointEntry(*before_idx + 1, mEndpointIterationHint); } -DataModel::ClusterEntry CodegenDataModelProvider::FirstCluster(EndpointId endpointId) +DataModel::ClusterEntry CodegenDataModelProvider::FirstServerCluster(EndpointId endpointId) { const EmberAfEndpointType * endpoint = emberAfFindEndpointType(endpointId); VerifyOrReturnValue(endpoint != nullptr, DataModel::ClusterEntry::kInvalid); VerifyOrReturnValue(endpoint->clusterCount > 0, DataModel::ClusterEntry::kInvalid); VerifyOrReturnValue(endpoint->cluster != nullptr, DataModel::ClusterEntry::kInvalid); - return FirstServerClusterEntry(endpointId, endpoint, 0, mClusterIterationHint); + return FirstServerClusterEntry(endpointId, endpoint, 0, mServerClusterIterationHint); } -std::optional CodegenDataModelProvider::TryFindServerClusterIndex(const EmberAfEndpointType * endpoint, - ClusterId id) const +std::optional CodegenDataModelProvider::TryFindClusterIndex(const EmberAfEndpointType * endpoint, ClusterId id, + ClusterSide side) const { const unsigned clusterCount = endpoint->clusterCount; + unsigned hint = side == ClusterSide::kServer ? mServerClusterIterationHint : mClientClusterIterationHint; - if (mClusterIterationHint < clusterCount) + if (hint < clusterCount) { - const EmberAfCluster & cluster = endpoint->cluster[mClusterIterationHint]; - if (cluster.IsServer() && (cluster.clusterId == id)) + const EmberAfCluster & cluster = endpoint->cluster[hint]; + if (((side == ClusterSide::kServer) && cluster.IsServer()) || ((side == ClusterSide::kClient) && cluster.IsClient())) { - return std::make_optional(mClusterIterationHint); + if (cluster.clusterId == id) + { + return std::make_optional(hint); + } } } @@ -488,7 +581,11 @@ std::optional CodegenDataModelProvider::TryFindServerClusterIndex(cons for (unsigned cluster_idx = 0; cluster_idx < clusterCount; cluster_idx++) { const EmberAfCluster & cluster = endpoint->cluster[cluster_idx]; - if (cluster.IsServer() && (cluster.clusterId == id)) + if (((side == ClusterSide::kServer) && !cluster.IsServer()) || ((side == ClusterSide::kClient) && !cluster.IsClient())) + { + continue; + } + if (cluster.clusterId == id) { return std::make_optional(cluster_idx); } @@ -497,7 +594,7 @@ std::optional CodegenDataModelProvider::TryFindServerClusterIndex(cons return std::nullopt; } -DataModel::ClusterEntry CodegenDataModelProvider::NextCluster(const ConcreteClusterPath & before) +DataModel::ClusterEntry CodegenDataModelProvider::NextServerCluster(const ConcreteClusterPath & before) { // TODO: This search still seems slow (ember will loop). Should use index hints as long // as ember API supports it @@ -507,16 +604,16 @@ DataModel::ClusterEntry CodegenDataModelProvider::NextCluster(const ConcreteClus VerifyOrReturnValue(endpoint->clusterCount > 0, DataModel::ClusterEntry::kInvalid); VerifyOrReturnValue(endpoint->cluster != nullptr, DataModel::ClusterEntry::kInvalid); - std::optional cluster_idx = TryFindServerClusterIndex(endpoint, before.mClusterId); + std::optional cluster_idx = TryFindClusterIndex(endpoint, before.mClusterId, ClusterSide::kServer); if (!cluster_idx.has_value()) { return DataModel::ClusterEntry::kInvalid; } - return FirstServerClusterEntry(before.mEndpointId, endpoint, *cluster_idx + 1, mClusterIterationHint); + return FirstServerClusterEntry(before.mEndpointId, endpoint, *cluster_idx + 1, mServerClusterIterationHint); } -std::optional CodegenDataModelProvider::GetClusterInfo(const ConcreteClusterPath & path) +std::optional CodegenDataModelProvider::GetServerClusterInfo(const ConcreteClusterPath & path) { const EmberAfCluster * cluster = FindServerCluster(path); @@ -537,6 +634,35 @@ std::optional CodegenDataModelProvider::GetClusterInfo(c return std::make_optional(std::get(info)); } +ConcreteClusterPath CodegenDataModelProvider::FirstClientCluster(EndpointId endpointId) +{ + const EmberAfEndpointType * endpoint = emberAfFindEndpointType(endpointId); + VerifyOrReturnValue(endpoint != nullptr, ConcreteClusterPath(endpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->clusterCount > 0, ConcreteClusterPath(endpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->cluster != nullptr, ConcreteClusterPath(endpointId, kInvalidClusterId)); + + return ConcreteClusterPath(endpointId, FirstClientClusterId(endpoint, 0, mClientClusterIterationHint)); +} + +ConcreteClusterPath CodegenDataModelProvider::NextClientCluster(const ConcreteClusterPath & before) +{ + // TODO: This search still seems slow (ember will loop). Should use index hints as long + // as ember API supports it + const EmberAfEndpointType * endpoint = emberAfFindEndpointType(before.mEndpointId); + + VerifyOrReturnValue(endpoint != nullptr, ConcreteClusterPath(before.mEndpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->clusterCount > 0, ConcreteClusterPath(before.mEndpointId, kInvalidClusterId)); + VerifyOrReturnValue(endpoint->cluster != nullptr, ConcreteClusterPath(before.mEndpointId, kInvalidClusterId)); + + std::optional cluster_idx = TryFindClusterIndex(endpoint, before.mClusterId, ClusterSide::kClient); + if (!cluster_idx.has_value()) + { + return ConcreteClusterPath(before.mEndpointId, kInvalidClusterId); + } + + return ConcreteClusterPath(before.mEndpointId, FirstClientClusterId(endpoint, *cluster_idx + 1, mClientClusterIterationHint)); +} + DataModel::AttributeEntry CodegenDataModelProvider::FirstAttribute(const ConcreteClusterPath & path) { const EmberAfCluster * cluster = FindServerCluster(path); @@ -772,5 +898,29 @@ std::optional CodegenDataModelProvider::NextDeviceTy return DeviceTypeEntryFromEmber(deviceTypes[idx]); } +std::optional CodegenDataModelProvider::GetFirstSemanticTag(EndpointId endpoint) +{ + Clusters::Descriptor::Structs::SemanticTagStruct::Type tag; + // we start at the beginning + mSemanticTagIterationHint = 0; + if (GetSemanticTagForEndpointAtIndex(endpoint, 0, tag) == CHIP_NO_ERROR) + { + return std::make_optional(tag); + } + return std::nullopt; +} + +std::optional CodegenDataModelProvider::GetNextSemanticTag(EndpointId endpoint, + const SemanticTag & previous) +{ + Clusters::Descriptor::Structs::SemanticTagStruct::Type tag; + std::optional idx = FindNextSemanticTagIndex(endpoint, previous, mSemanticTagIterationHint); + if (idx.has_value() && GetSemanticTagForEndpointAtIndex(endpoint, *idx, tag) == CHIP_NO_ERROR) + { + return std::make_optional(tag); + } + return std::nullopt; +} + } // namespace app } // namespace chip diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h index 59b91747a0..35193a492f 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.h +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.h @@ -149,17 +149,24 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override; /// attribute tree iteration - EndpointId FirstEndpoint() override; - EndpointId NextEndpoint(EndpointId before) override; + DataModel::EndpointEntry FirstEndpoint() override; + DataModel::EndpointEntry NextEndpoint(EndpointId before) override; + std::optional GetEndpointInfo(EndpointId endpoint) override; bool EndpointExists(EndpointId endpoint) override; std::optional FirstDeviceType(EndpointId endpoint) override; std::optional NextDeviceType(EndpointId endpoint, const DataModel::DeviceTypeEntry & previous) override; - DataModel::ClusterEntry FirstCluster(EndpointId endpoint) override; - DataModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; - std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + std::optional GetFirstSemanticTag(EndpointId endpoint) override; + std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) override; + + DataModel::ClusterEntry FirstServerCluster(EndpointId endpoint) override; + DataModel::ClusterEntry NextServerCluster(const ConcreteClusterPath & before) override; + std::optional GetServerClusterInfo(const ConcreteClusterPath & path) override; + + ConcreteClusterPath FirstClientCluster(EndpointId endpoint) override; + ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) override; DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; @@ -175,10 +182,12 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider private: // Iteration is often done in a tight loop going through all values. // To avoid N^2 iterations, cache a hint of where something is positioned - uint16_t mEndpointIterationHint = 0; - unsigned mClusterIterationHint = 0; - unsigned mAttributeIterationHint = 0; - unsigned mDeviceTypeIterationHint = 0; + uint16_t mEndpointIterationHint = 0; + unsigned mServerClusterIterationHint = 0; + unsigned mClientClusterIterationHint = 0; + unsigned mAttributeIterationHint = 0; + unsigned mDeviceTypeIterationHint = 0; + unsigned mSemanticTagIterationHint = 0; EmberCommandListIterator mAcceptedCommandsIterator; EmberCommandListIterator mGeneratedCommandsIterator; @@ -191,6 +200,13 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider ClusterReference(const ConcreteClusterPath p, const EmberAfCluster * c) : path(p), cluster(c) {} }; + + enum class ClusterSide : uint8_t + { + kServer, + kClient, + }; + std::optional mPreviouslyFoundCluster; unsigned mEmberMetadataStructureGeneration = 0; @@ -203,7 +219,8 @@ class CodegenDataModelProvider : public chip::app::DataModel::Provider std::optional TryFindAttributeIndex(const EmberAfCluster * cluster, chip::AttributeId id) const; /// Find the index of the given cluster id - std::optional TryFindServerClusterIndex(const EmberAfEndpointType * endpoint, chip::ClusterId id) const; + std::optional TryFindClusterIndex(const EmberAfEndpointType * endpoint, chip::ClusterId id, + ClusterSide clusterSide) const; /// Find the index of the given endpoint id std::optional TryFindEndpointIndex(chip::EndpointId id) const; diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp index de2f888647..7dcfe7fecc 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider_Write.cpp @@ -190,7 +190,7 @@ DataModel::ActionReturnStatus CodegenDataModelProvider::WriteAttribute(const Dat if (request.path.mDataVersion.HasValue()) { - std::optional clusterInfo = GetClusterInfo(request.path); + std::optional clusterInfo = GetServerClusterInfo(request.path); if (!clusterInfo.has_value()) { ChipLogError(DataManagement, "Unable to get cluster info for Endpoint 0x%x, Cluster " ChipLogFormatMEI, diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index c9b2a1b99a..50d8ec67df 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -96,6 +96,17 @@ constexpr uint8_t kDeviceTypeId2Version = 11; constexpr DeviceTypeId kDeviceTypeId3 = 3; constexpr uint8_t kDeviceTypeId3Version = 33; +constexpr uint8_t kNamespaceID1 = 123; +constexpr uint8_t kTag1 = 10; +constexpr char kLabel1[] = "Label1"; + +constexpr uint8_t kNamespaceID2 = 254; +constexpr uint8_t kTag2 = 22; +constexpr char kLabel2[] = "Label2"; + +constexpr uint8_t kNamespaceID3 = 3; +constexpr uint8_t kTag3 = 32; + static_assert(kEndpointIdThatIsMissing != kInvalidEndpointId); static_assert(kEndpointIdThatIsMissing != kMockEndpoint1); static_assert(kEndpointIdThatIsMissing != kMockEndpoint2); @@ -280,10 +291,16 @@ const MockNodeConfig gTestNodeConfig({ MockClusterConfig(MockClusterId(2), { ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), }), + MockClusterConfig(MockClusterId(3), {}, {}, {}, {}, BitMask().Set(MockClusterSide::kClient)), + MockClusterConfig(MockClusterId(4), {}, {}, {}, {}, BitMask().Set(MockClusterSide::kClient)), }, { { kDeviceTypeId1, kDeviceTypeId1Version}, { kDeviceTypeId2, kDeviceTypeId2Version}, { kDeviceTypeId3, kDeviceTypeId3Version}, + },{ + { MakeNullable(VendorId::TestVendor1), kNamespaceID1, kTag1, MakeOptional(MakeNullable(CharSpan::fromCharString(kLabel1)))}, + { Nullable(), kNamespaceID2, kTag2, MakeOptional(MakeNullable(CharSpan::fromCharString(kLabel2)))}, + { MakeNullable(VendorId::TestVendor3), kNamespaceID3, kTag3, NullOptional}, }), MockEndpointConfig(kMockEndpoint2, { MockClusterConfig(MockClusterId(1), { @@ -308,11 +325,14 @@ const MockNodeConfig gTestNodeConfig({ }, /* attributes */ {}, /* events */ {11}, /* acceptedCommands */ - {4, 6} /* generatedCommands */ + {4, 6}, /* generatedCommands */ + BitMask().Set(MockClusterSide::kClient).Set(MockClusterSide::kServer) ), + MockClusterConfig(MockClusterId(4), {}, {}, {}, {}, MockClusterSide::kClient), }, { { kDeviceTypeId2, kDeviceTypeId2Version}, - }), + }, {}, + EndpointComposition::kTree), MockEndpointConfig(kMockEndpoint3, { MockClusterConfig(MockClusterId(1), { ClusterRevision::Id, FeatureMap::Id, MockAttributeId(1), @@ -875,43 +895,109 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) CodegenDataModelProviderWithContext model; // This iteration relies on the hard-coding that occurs when mock_ember is used - EXPECT_EQ(model.FirstEndpoint(), kMockEndpoint1); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint3), kInvalidEndpointId); + EndpointEntry ep = model.FirstEndpoint(); + EXPECT_EQ(ep.id, kMockEndpoint1); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint3); + EXPECT_EQ(ep.id, kInvalidEndpointId); /// Some out of order requests should work as well - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint2), kMockEndpoint3); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint1), kMockEndpoint2); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint3), kInvalidEndpointId); - EXPECT_EQ(model.NextEndpoint(kMockEndpoint3), kInvalidEndpointId); - EXPECT_EQ(model.FirstEndpoint(), kMockEndpoint1); - EXPECT_EQ(model.FirstEndpoint(), kMockEndpoint1); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint2); + EXPECT_EQ(ep.id, kMockEndpoint3); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.NextEndpoint(kMockEndpoint1); + EXPECT_EQ(ep.id, kMockEndpoint2); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + ep = model.NextEndpoint(kMockEndpoint3); + EXPECT_EQ(ep.id, kInvalidEndpointId); + ep = model.NextEndpoint(kMockEndpoint3); + EXPECT_EQ(ep.id, kInvalidEndpointId); + ep = model.FirstEndpoint(); + EXPECT_EQ(ep.id, kMockEndpoint1); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + ep = model.FirstEndpoint(); + EXPECT_EQ(ep.id, kMockEndpoint1); + EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + + // invalid endpoiunts + ep = model.NextEndpoint(kInvalidEndpointId); + EXPECT_EQ(ep.id, kInvalidEndpointId); + ep = model.NextEndpoint(987u); + EXPECT_EQ(ep.id, kInvalidEndpointId); +} + +TEST(TestCodegenModelViaMocks, GetEndpointInfo) +{ + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + std::optional info = model.GetEndpointInfo(kMockEndpoint1); + ASSERT_TRUE(info.has_value()); + EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) + EndpointCompositionPattern::kFullFamilyPattern); + info = model.GetEndpointInfo(kMockEndpoint2); + ASSERT_TRUE(info.has_value()); + EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) + EndpointCompositionPattern::kTreePattern); + info = model.GetEndpointInfo(kMockEndpoint3); + ASSERT_TRUE(info.has_value()); + EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) + EndpointCompositionPattern::kFullFamilyPattern); // invalid endpoiunts - EXPECT_EQ(model.NextEndpoint(kInvalidEndpointId), kInvalidEndpointId); - EXPECT_EQ(model.NextEndpoint(987u), kInvalidEndpointId); + info = model.GetEndpointInfo(kInvalidEndpointId); + EXPECT_FALSE(info.has_value()); + info = model.GetEndpointInfo(987u); + EXPECT_FALSE(info.has_value()); } -TEST(TestCodegenModelViaMocks, IterateOverClusters) +TEST(TestCodegenModelViaMocks, IterateOverServerClusters) { UseMockNodeConfig config(gTestNodeConfig); CodegenDataModelProviderWithContext model; chip::Test::ResetVersion(); - EXPECT_FALSE(model.FirstCluster(kEndpointIdThatIsMissing).path.HasValidIds()); - EXPECT_FALSE(model.FirstCluster(kInvalidEndpointId).path.HasValidIds()); - EXPECT_FALSE(model.NextCluster(ConcreteClusterPath(kInvalidEndpointId, 123)).path.HasValidIds()); - EXPECT_FALSE(model.NextCluster(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).path.HasValidIds()); - EXPECT_FALSE(model.NextCluster(ConcreteClusterPath(kMockEndpoint1, 981u)).path.HasValidIds()); + EXPECT_FALSE(model.FirstServerCluster(kEndpointIdThatIsMissing).path.HasValidIds()); + EXPECT_FALSE(model.FirstServerCluster(kInvalidEndpointId).path.HasValidIds()); + EXPECT_FALSE(model.NextServerCluster(ConcreteClusterPath(kInvalidEndpointId, 123)).path.HasValidIds()); + EXPECT_FALSE(model.NextServerCluster(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).path.HasValidIds()); + EXPECT_FALSE(model.NextServerCluster(ConcreteClusterPath(kMockEndpoint1, 981u)).path.HasValidIds()); // mock endpoint 1 has 2 mock clusters: 1 and 2 - ClusterEntry entry = model.FirstCluster(kMockEndpoint1); + ClusterEntry entry = model.FirstServerCluster(kMockEndpoint1); ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(entry.path.mClusterId, MockClusterId(1)); @@ -920,31 +1006,31 @@ TEST(TestCodegenModelViaMocks, IterateOverClusters) chip::Test::BumpVersion(); - entry = model.NextCluster(entry.path); + entry = model.NextServerCluster(entry.path); ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(entry.path.mClusterId, MockClusterId(2)); EXPECT_EQ(entry.info.dataVersion, 1u); EXPECT_EQ(entry.info.flags.Raw(), 0u); - entry = model.NextCluster(entry.path); + entry = model.NextServerCluster(entry.path); EXPECT_FALSE(entry.path.HasValidIds()); // mock endpoint 3 has 4 mock clusters: 1 through 4 - entry = model.FirstCluster(kMockEndpoint3); + entry = model.FirstServerCluster(kMockEndpoint3); for (uint16_t clusterId = 1; clusterId <= 4; clusterId++) { ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint3); EXPECT_EQ(entry.path.mClusterId, MockClusterId(clusterId)); - entry = model.NextCluster(entry.path); + entry = model.NextServerCluster(entry.path); } EXPECT_FALSE(entry.path.HasValidIds()); // repeat calls should work for (int i = 0; i < 10; i++) { - entry = model.FirstCluster(kMockEndpoint1); + entry = model.FirstServerCluster(kMockEndpoint1); ASSERT_TRUE(entry.path.HasValidIds()); EXPECT_EQ(entry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(entry.path.mClusterId, MockClusterId(1)); @@ -952,14 +1038,14 @@ TEST(TestCodegenModelViaMocks, IterateOverClusters) for (int i = 0; i < 10; i++) { - ClusterEntry nextEntry = model.NextCluster(entry.path); + ClusterEntry nextEntry = model.NextServerCluster(entry.path); ASSERT_TRUE(nextEntry.path.HasValidIds()); EXPECT_EQ(nextEntry.path.mEndpointId, kMockEndpoint1); EXPECT_EQ(nextEntry.path.mClusterId, MockClusterId(2)); } } -TEST(TestCodegenModelViaMocks, GetClusterInfo) +TEST(TestCodegenModelViaMocks, GetServerClusterInfo) { UseMockNodeConfig config(gTestNodeConfig); @@ -967,24 +1053,78 @@ TEST(TestCodegenModelViaMocks, GetClusterInfo) chip::Test::ResetVersion(); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kInvalidEndpointId, kInvalidClusterId)).has_value()); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kInvalidEndpointId, MockClusterId(1))).has_value()); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).has_value()); - ASSERT_FALSE(model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(10))).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kInvalidEndpointId, kInvalidClusterId)).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kInvalidEndpointId, MockClusterId(1))).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).has_value()); + ASSERT_FALSE(model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(10))).has_value()); // now get the value - std::optional info = model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); + std::optional info = model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->dataVersion, 0u); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->flags.Raw(), 0u); // NOLINT(bugprone-unchecked-optional-access) chip::Test::BumpVersion(); - info = model.GetClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); + info = model.GetServerClusterInfo(ConcreteClusterPath(kMockEndpoint1, MockClusterId(1))); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->dataVersion, 1u); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->flags.Raw(), 0u); // NOLINT(bugprone-unchecked-optional-access) } +TEST(TestCodegenModelViaMocks, IterateOverClientClusters) +{ + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + EXPECT_FALSE(model.FirstClientCluster(kEndpointIdThatIsMissing).HasValidIds()); + EXPECT_FALSE(model.FirstClientCluster(kInvalidEndpointId).HasValidIds()); + EXPECT_FALSE(model.NextClientCluster(ConcreteClusterPath(kInvalidEndpointId, 123)).HasValidIds()); + EXPECT_FALSE(model.NextClientCluster(ConcreteClusterPath(kMockEndpoint1, kInvalidClusterId)).HasValidIds()); + EXPECT_FALSE(model.NextClientCluster(ConcreteClusterPath(kMockEndpoint1, 981u)).HasValidIds()); + + // mock endpoint 1 has 2 mock client clusters: 3 and 4 + ConcreteClusterPath path = model.FirstClientCluster(kMockEndpoint1); + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint1); + EXPECT_EQ(path.mClusterId, MockClusterId(3)); + + path = model.NextClientCluster(path); + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint1); + EXPECT_EQ(path.mClusterId, MockClusterId(4)); + + path = model.NextClientCluster(path); + EXPECT_FALSE(path.HasValidIds()); + + // mock endpoint 2 has 1 mock client clusters: 3(has server side at the same time) and 4 + path = model.FirstClientCluster(kMockEndpoint2); + for (uint16_t clusterId = 3; clusterId <= 4; clusterId++) + { + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint2); + EXPECT_EQ(path.mClusterId, MockClusterId(clusterId)); + path = model.NextClientCluster(path); + } + EXPECT_FALSE(path.HasValidIds()); + + // repeat calls should work + for (int i = 0; i < 10; i++) + { + path = model.FirstClientCluster(kMockEndpoint1); + ASSERT_TRUE(path.HasValidIds()); + EXPECT_EQ(path.mEndpointId, kMockEndpoint1); + EXPECT_EQ(path.mClusterId, MockClusterId(3)); + } + + for (int i = 0; i < 10; i++) + { + ConcreteClusterPath nextPath = model.NextClientCluster(path); + ASSERT_TRUE(nextPath.HasValidIds()); + EXPECT_EQ(nextPath.mEndpointId, kMockEndpoint1); + EXPECT_EQ(nextPath.mClusterId, MockClusterId(4)); + } +} + TEST(TestCodegenModelViaMocks, IterateOverAttributes) { UseMockNodeConfig config(gTestNodeConfig); @@ -2569,15 +2709,15 @@ TEST(TestCodegenModelViaMocks, DeviceTypeIteration) // Mock endpoint 1 has 3 device types std::optional entry = model.FirstDeviceType(kMockEndpoint1); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeVersion = kDeviceTypeId1Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeRevision = kDeviceTypeId1Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeVersion = kDeviceTypeId2Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeRevision = kDeviceTypeId2Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeVersion = kDeviceTypeId3Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeRevision = kDeviceTypeId3Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_FALSE(entry.has_value()); @@ -2585,19 +2725,19 @@ TEST(TestCodegenModelViaMocks, DeviceTypeIteration) // Mock endpoint 2 has 1 device types entry = model.FirstDeviceType(kMockEndpoint2); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeVersion = kDeviceTypeId2Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeRevision = kDeviceTypeId2Version })); // NOLINTNEXTLINE(bugprone-unchecked-optional-access): Assert above that this is not none entry = model.NextDeviceType(kMockEndpoint2, *entry); ASSERT_FALSE(entry.has_value()); // out of order query works - entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeVersion = kDeviceTypeId2Version }); + entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId2, .deviceTypeRevision = kDeviceTypeId2Version }); entry = model.NextDeviceType(kMockEndpoint1, *entry); ASSERT_EQ(entry, - std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeVersion = kDeviceTypeId3Version })); + std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId3, .deviceTypeRevision = kDeviceTypeId3Version })); // invalid query fails - entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeVersion = kDeviceTypeId1Version }); + entry = std::make_optional(DeviceTypeEntry{ .deviceTypeId = kDeviceTypeId1, .deviceTypeRevision = kDeviceTypeId1Version }); entry = model.NextDeviceType(kMockEndpoint2, *entry); ASSERT_FALSE(entry.has_value()); @@ -2605,3 +2745,60 @@ TEST(TestCodegenModelViaMocks, DeviceTypeIteration) entry = model.FirstDeviceType(kMockEndpoint3); ASSERT_FALSE(entry.has_value()); } + +TEST(TestCodegenModelViaMocks, SemanticTagIteration) +{ + UseMockNodeConfig config(gTestNodeConfig); + CodegenDataModelProviderWithContext model; + + // Mock endpoint 1 has 3 semantic tags + std::optional tag = model.GetFirstSemanticTag(kMockEndpoint1); + ASSERT_TRUE(tag.has_value()); + EXPECT_EQ(tag->mfgCode, MakeNullable(VendorId::TestVendor1)); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID1); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag1); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag->label.HasValue() && (!tag->label.Value().IsNull())); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE( + tag->label.Value().Value().data_equal(CharSpan::fromCharString(kLabel1))); // NOLINT(bugprone-unchecked-optional-access) + tag = model.GetNextSemanticTag(kMockEndpoint1, *tag); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag.has_value()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE(tag->mfgCode.IsNull()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID2); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag2); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag->label.HasValue() && (!tag->label.Value().IsNull())); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE( + tag->label.Value().Value().data_equal(CharSpan::fromCharString(kLabel2))); // NOLINT(bugprone-unchecked-optional-access) + tag = model.GetNextSemanticTag(kMockEndpoint1, *tag); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag.has_value()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->mfgCode, MakeNullable(VendorId::TestVendor3)); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID3); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag3); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_FALSE(tag->label.HasValue()); // NOLINT(bugprone-unchecked-optional-access) + tag = model.GetNextSemanticTag(kMockEndpoint1, *tag); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_FALSE(tag.has_value()); + + // out of order query works + DataModel::Provider::SemanticTag existTag = { + .mfgCode = MakeNullable(VendorId::TestVendor1), + .namespaceID = kNamespaceID1, + .tag = kTag1, + .label = MakeOptional(MakeNullable(CharSpan::fromCharString(kLabel1))), + }; + tag = model.GetNextSemanticTag(kMockEndpoint1, existTag); + ASSERT_TRUE(tag.has_value()); + EXPECT_TRUE(tag->mfgCode.IsNull()); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->namespaceID, kNamespaceID2); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_EQ(tag->tag, kTag2); // NOLINT(bugprone-unchecked-optional-access) + ASSERT_TRUE(tag->label.HasValue() && (!tag->label.Value().IsNull())); // NOLINT(bugprone-unchecked-optional-access) + EXPECT_TRUE( + tag->label.Value().Value().data_equal(CharSpan::fromCharString(kLabel2))); // NOLINT(bugprone-unchecked-optional-access) + + // invalid query fails + existTag.tag = kTag2; + tag = model.GetNextSemanticTag(kMockEndpoint1, existTag); + ASSERT_FALSE(tag.has_value()); + + // empty endpoint works + tag = model.GetFirstSemanticTag(kMockEndpoint2); + ASSERT_FALSE(tag.has_value()); +} diff --git a/src/app/data-model-provider/MetadataTypes.cpp b/src/app/data-model-provider/MetadataTypes.cpp index ed3e2667dd..2729698c49 100644 --- a/src/app/data-model-provider/MetadataTypes.cpp +++ b/src/app/data-model-provider/MetadataTypes.cpp @@ -30,12 +30,14 @@ const ClusterEntry ClusterEntry::kInvalid{ .info = ClusterInfo(0 /* version */), // version of invalid cluster entry does not matter }; +const EndpointEntry EndpointEntry::kInvalid{ .id = kInvalidEndpointId, .info = EndpointInfo(kInvalidEndpointId) }; + // A default implementation if just first/next exist bool ProviderMetadataTree::EndpointExists(EndpointId endpoint) { - for (EndpointId id = FirstEndpoint(); id != kInvalidEndpointId; id = NextEndpoint(id)) + for (EndpointEntry ep = FirstEndpoint(); ep.IsValid(); ep = NextEndpoint(ep.id)) { - if (id == endpoint) + if (ep.id == endpoint) { return true; } diff --git a/src/app/data-model-provider/MetadataTypes.h b/src/app/data-model-provider/MetadataTypes.h index c1d173c985..ab9005412e 100644 --- a/src/app/data-model-provider/MetadataTypes.h +++ b/src/app/data-model-provider/MetadataTypes.h @@ -20,16 +20,46 @@ #include #include +#include #include #include #include +#include #include #include +#include namespace chip { namespace app { namespace DataModel { +enum class EndpointCompositionPattern : uint8_t +{ + kTreePattern = 0x1, + kFullFamilyPattern = 0x2, +}; + +struct EndpointInfo +{ + // kInvalidEndpointId if there is no explicit parent endpoint (which means the parent is endpoint 0, + // for endpoints other than endpoint 0). + EndpointId parentId; + EndpointCompositionPattern compositionPattern; + + explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamilyPattern) + {} + explicit EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {} +}; + +struct EndpointEntry +{ + EndpointId id; + EndpointInfo info; + + bool IsValid() const { return id != kInvalidEndpointId; } + static const EndpointEntry kInvalid; +}; + enum class ClusterQualityFlags : uint32_t { kDiagnosticsData = 0x0001, // `K` quality, may be filtered out in subscriptions @@ -111,11 +141,11 @@ struct CommandEntry struct DeviceTypeEntry { DeviceTypeId deviceTypeId; - uint8_t deviceTypeVersion; + uint8_t deviceTypeRevision; bool operator==(const DeviceTypeEntry & other) const { - return (deviceTypeId == other.deviceTypeId) && (deviceTypeVersion == other.deviceTypeVersion); + return (deviceTypeId == other.deviceTypeId) && (deviceTypeRevision == other.deviceTypeRevision); } }; @@ -140,18 +170,31 @@ class ProviderMetadataTree public: virtual ~ProviderMetadataTree() = default; - virtual EndpointId FirstEndpoint() = 0; - virtual EndpointId NextEndpoint(EndpointId before) = 0; + // This iteration will list all the endpoints in the data model + virtual EndpointEntry FirstEndpoint() = 0; + virtual EndpointEntry NextEndpoint(EndpointId before) = 0; + virtual std::optional GetEndpointInfo(EndpointId id) = 0; virtual bool EndpointExists(EndpointId id); // This iteration describes device types registered on an endpoint virtual std::optional FirstDeviceType(EndpointId endpoint) = 0; virtual std::optional NextDeviceType(EndpointId endpoint, const DeviceTypeEntry & previous) = 0; - // This iteration will list all clusters on a given endpoint - virtual ClusterEntry FirstCluster(EndpointId endpoint) = 0; - virtual ClusterEntry NextCluster(const ConcreteClusterPath & before) = 0; - virtual std::optional GetClusterInfo(const ConcreteClusterPath & path) = 0; + // This iteration describes semantic tags registered on an endpoint + using SemanticTag = Clusters::Descriptor::Structs::SemanticTagStruct::Type; + virtual std::optional GetFirstSemanticTag(EndpointId endpoint) = 0; + virtual std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) = 0; + + // This iteration will list all server clusters on a given endpoint + virtual ClusterEntry FirstServerCluster(EndpointId endpoint) = 0; + virtual ClusterEntry NextServerCluster(const ConcreteClusterPath & before) = 0; + virtual std::optional GetServerClusterInfo(const ConcreteClusterPath & path) = 0; + + // This iteration will list all client clusters on a given endpoint + // As the client cluster is only a client without any attributes/commands, + // these functions only return the cluster path. + virtual ConcreteClusterPath FirstClientCluster(EndpointId endpoint) = 0; + virtual ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) = 0; // Attribute iteration and accessors provide cluster-level access over // attributes diff --git a/src/app/dynamic_server/DynamicDispatcher.cpp b/src/app/dynamic_server/DynamicDispatcher.cpp index ba4525e2fc..634055a985 100644 --- a/src/app/dynamic_server/DynamicDispatcher.cpp +++ b/src/app/dynamic_server/DynamicDispatcher.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -274,6 +275,28 @@ Protocols::InteractionModel::Status emAfReadOrWriteAttribute(const EmberAfAttrib return Protocols::InteractionModel::Status::UnsupportedAttribute; } +namespace chip { +namespace app { + +EndpointComposition GetCompositionForEndpointIndex(uint16_t endpointIndex) +{ + return EndpointComposition::kFullFamily; +} + +} // namespace app +} // namespace chip + +EndpointId emberAfParentEndpointFromIndex(uint16_t index) +{ + return kInvalidEndpointId; +} + +CHIP_ERROR GetSemanticTagForEndpointAtIndex(EndpointId endpoint, size_t index, + Clusters::Descriptor::Structs::SemanticTagStruct::Type & tag) +{ + return CHIP_ERROR_NOT_FOUND; +} + void emberAfAttributeChanged(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId, AttributesChangedListener * listener) { diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 63d71bfc92..e2691e519a 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -51,7 +51,7 @@ using Protocols::InteractionModel::Status; Status EventPathValid(DataModel::Provider * model, const ConcreteEventPath & eventPath) { - if (!model->GetClusterInfo(eventPath).has_value()) + if (!model->GetServerClusterInfo(eventPath).has_value()) { return model->EndpointExists(eventPath.mEndpointId) ? Status::UnsupportedCluster : Status::UnsupportedEndpoint; } @@ -148,7 +148,7 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode readRequest.path = path; DataVersion version = 0; - if (std::optional clusterInfo = dataModel->GetClusterInfo(path); clusterInfo.has_value()) + if (std::optional clusterInfo = dataModel->GetServerClusterInfo(path); clusterInfo.has_value()) { version = clusterInfo->dataVersion; } @@ -208,7 +208,7 @@ DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataMode bool IsClusterDataVersionEqualTo(DataModel::Provider * dataModel, const ConcreteClusterPath & path, DataVersion dataVersion) { - std::optional info = dataModel->GetClusterInfo(path); + std::optional info = dataModel->GetServerClusterInfo(path); if (!info.has_value()) { return false; diff --git a/src/app/tests/test-interaction-model-api.cpp b/src/app/tests/test-interaction-model-api.cpp index d263e251d2..867d4c895e 100644 --- a/src/app/tests/test-interaction-model-api.cpp +++ b/src/app/tests/test-interaction-model-api.cpp @@ -149,16 +149,21 @@ std::optional TestImCustomDataModel::Invoke(const InvokeRequ return std::make_optional(CHIP_ERROR_NOT_IMPLEMENTED); } -EndpointId TestImCustomDataModel::FirstEndpoint() +DataModel::EndpointEntry TestImCustomDataModel::FirstEndpoint() { return CodegenDataModelProviderInstance()->FirstEndpoint(); } -EndpointId TestImCustomDataModel::NextEndpoint(EndpointId before) +DataModel::EndpointEntry TestImCustomDataModel::NextEndpoint(EndpointId before) { return CodegenDataModelProviderInstance()->NextEndpoint(before); } +std::optional TestImCustomDataModel::GetEndpointInfo(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->GetEndpointInfo(endpoint); +} + std::optional TestImCustomDataModel::FirstDeviceType(EndpointId endpoint) { return std::nullopt; @@ -170,19 +175,40 @@ std::optional TestImCustomDataModel::NextDeviceType( return std::nullopt; } -ClusterEntry TestImCustomDataModel::FirstCluster(EndpointId endpoint) +std::optional TestImCustomDataModel::GetFirstSemanticTag(EndpointId endpoint) +{ + return std::nullopt; +} + +std::optional TestImCustomDataModel::GetNextSemanticTag(EndpointId endpoint, + const SemanticTag & previous) +{ + return std::nullopt; +} + +ClusterEntry TestImCustomDataModel::FirstServerCluster(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->FirstServerCluster(endpoint); +} + +ClusterEntry TestImCustomDataModel::NextServerCluster(const ConcreteClusterPath & before) +{ + return CodegenDataModelProviderInstance()->NextServerCluster(before); +} + +std::optional TestImCustomDataModel::GetServerClusterInfo(const ConcreteClusterPath & path) { - return CodegenDataModelProviderInstance()->FirstCluster(endpoint); + return CodegenDataModelProviderInstance()->GetServerClusterInfo(path); } -ClusterEntry TestImCustomDataModel::NextCluster(const ConcreteClusterPath & before) +ConcreteClusterPath TestImCustomDataModel::FirstClientCluster(EndpointId endpoint) { - return CodegenDataModelProviderInstance()->NextCluster(before); + return CodegenDataModelProviderInstance()->FirstClientCluster(endpoint); } -std::optional TestImCustomDataModel::GetClusterInfo(const ConcreteClusterPath & path) +ConcreteClusterPath TestImCustomDataModel::NextClientCluster(const ConcreteClusterPath & before) { - return CodegenDataModelProviderInstance()->GetClusterInfo(path); + return CodegenDataModelProviderInstance()->NextClientCluster(before); } AttributeEntry TestImCustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster) diff --git a/src/app/tests/test-interaction-model-api.h b/src/app/tests/test-interaction-model-api.h index 0e0fd2c0e5..d382ccd809 100644 --- a/src/app/tests/test-interaction-model-api.h +++ b/src/app/tests/test-interaction-model-api.h @@ -110,14 +110,19 @@ class TestImCustomDataModel : public DataModel::Provider std::optional Invoke(const DataModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override; - EndpointId FirstEndpoint() override; - EndpointId NextEndpoint(EndpointId before) override; + DataModel::EndpointEntry FirstEndpoint() override; + DataModel::EndpointEntry NextEndpoint(EndpointId before) override; + std::optional GetEndpointInfo(EndpointId endpoint) override; std::optional FirstDeviceType(EndpointId endpoint) override; std::optional NextDeviceType(EndpointId endpoint, const DataModel::DeviceTypeEntry & previous) override; - DataModel::ClusterEntry FirstCluster(EndpointId endpoint) override; - DataModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; - std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + std::optional GetFirstSemanticTag(EndpointId endpoint) override; + std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) override; + DataModel::ClusterEntry FirstServerCluster(EndpointId endpoint) override; + DataModel::ClusterEntry NextServerCluster(const ConcreteClusterPath & before) override; + std::optional GetServerClusterInfo(const ConcreteClusterPath & path) override; + ConcreteClusterPath FirstClientCluster(EndpointId endpoint) override; + ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) override; DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; std::optional GetAttributeInfo(const ConcreteAttributePath & path) override; diff --git a/src/app/util/af-types.h b/src/app/util/af-types.h index 04275a2515..e3559069ed 100644 --- a/src/app/util/af-types.h +++ b/src/app/util/af-types.h @@ -120,6 +120,8 @@ struct EmberAfCluster uint16_t eventCount; bool IsServer() const { return (mask & CLUSTER_MASK_SERVER) != 0; } + + bool IsClient() const { return (mask & CLUSTER_MASK_CLIENT) != 0; } }; /** diff --git a/src/app/util/attribute-storage.cpp b/src/app/util/attribute-storage.cpp index 4d9cc2368f..3df2ba7c66 100644 --- a/src/app/util/attribute-storage.cpp +++ b/src/app/util/attribute-storage.cpp @@ -1415,6 +1415,20 @@ bool IsTreeCompositionForEndpoint(EndpointId endpoint) return emAfEndpoints[index].bitmask.Has(EmberAfEndpointOptions::isTreeComposition); } +EndpointComposition GetCompositionForEndpointIndex(uint16_t endpointIndex) +{ + VerifyOrReturnValue(endpointIndex < ArraySize(emAfEndpoints), EndpointComposition::kInvalid); + if (emAfEndpoints[endpointIndex].bitmask.Has(EmberAfEndpointOptions::isFlatComposition)) + { + return EndpointComposition::kFullFamily; + } + if (emAfEndpoints[endpointIndex].bitmask.Has(EmberAfEndpointOptions::isTreeComposition)) + { + return EndpointComposition::kTree; + } + return EndpointComposition::kInvalid; +} + } // namespace app } // namespace chip diff --git a/src/app/util/attribute-storage.h b/src/app/util/attribute-storage.h index 711f6a7cff..6930db7a96 100644 --- a/src/app/util/attribute-storage.h +++ b/src/app/util/attribute-storage.h @@ -378,5 +378,17 @@ bool IsFlatCompositionForEndpoint(EndpointId endpoint); */ bool IsTreeCompositionForEndpoint(EndpointId endpoint); +enum class EndpointComposition : uint8_t +{ + kFullFamily, + kTree, + kInvalid, +}; + +/** + * @brief Returns the composition for a given endpoint index + */ +EndpointComposition GetCompositionForEndpointIndex(uint16_t index); + } // namespace app } // namespace chip diff --git a/src/app/util/mock/MockNodeConfig.cpp b/src/app/util/mock/MockNodeConfig.cpp index c6572ed0ae..bb919318e3 100644 --- a/src/app/util/mock/MockNodeConfig.cpp +++ b/src/app/util/mock/MockNodeConfig.cpp @@ -115,7 +115,7 @@ const T * findById(const std::vector & vector, decltype(std::declval().id) MockClusterConfig::MockClusterConfig(ClusterId aId, std::initializer_list aAttributes, std::initializer_list aEvents, std::initializer_list aAcceptedCommands, - std::initializer_list aGeneratedCommands) : + std::initializer_list aGeneratedCommands, BitMask side) : id(aId), attributes(aAttributes), events(aEvents), mEmberCluster{}, mAcceptedCommands(aAcceptedCommands), mGeneratedCommands(aGeneratedCommands) @@ -127,9 +127,17 @@ MockClusterConfig::MockClusterConfig(ClusterId aId, std::initializer_list(attributes.size()); - mEmberCluster.mask = CLUSTER_MASK_SERVER; mEmberCluster.eventCount = static_cast(mEmberEventList.size()); mEmberCluster.eventList = mEmberEventList.data(); @@ -177,9 +185,11 @@ const MockAttributeConfig * MockClusterConfig::attributeById(AttributeId attribu } MockEndpointConfig::MockEndpointConfig(EndpointId aId, std::initializer_list aClusters, - std::initializer_list aDeviceTypes) : + std::initializer_list aDeviceTypes, + std::initializer_list aTags, + app::EndpointComposition aComposition) : id(aId), - clusters(aClusters), mDeviceTypes(aDeviceTypes), mEmberEndpoint{} + composition(aComposition), clusters(aClusters), mDeviceTypes(aDeviceTypes), mSemanticTags(aTags), mEmberEndpoint{} { VerifyOrDie(aClusters.size() < UINT8_MAX); @@ -193,8 +203,8 @@ MockEndpointConfig::MockEndpointConfig(EndpointId aId, std::initializer_list #include +#include #include #include @@ -74,11 +75,18 @@ struct MockEventConfig const EventId id; }; +enum class MockClusterSide : uint8_t +{ + kServer = 0x1, + kClient = 0x2, +}; + struct MockClusterConfig { MockClusterConfig(ClusterId aId, std::initializer_list aAttributes = {}, std::initializer_list aEvents = {}, std::initializer_list aAcceptedCommands = {}, - std::initializer_list aGeneratedCommands = {}); + std::initializer_list aGeneratedCommands = {}, + BitMask side = BitMask().Set(MockClusterSide::kServer)); // Cluster-config is self-referential: mEmberCluster.attributes references mAttributeMetaData.data() MockClusterConfig(const MockClusterConfig & other); @@ -102,7 +110,9 @@ struct MockClusterConfig struct MockEndpointConfig { MockEndpointConfig(EndpointId aId, std::initializer_list aClusters = {}, - std::initializer_list aDeviceTypes = {}); + std::initializer_list aDeviceTypes = {}, + std::initializer_list aTags = {}, + app::EndpointComposition composition = app::EndpointComposition::kFullFamily); // Endpoint-config is self-referential: mEmberEndpoint.clusters references mEmberClusters.data() MockEndpointConfig(const MockEndpointConfig & other); @@ -115,12 +125,19 @@ struct MockEndpointConfig return Span(mDeviceTypes.data(), mDeviceTypes.size()); } + Span semanticTags() const + { + return Span(mSemanticTags.data(), mSemanticTags.size()); + } + const EndpointId id; + const app::EndpointComposition composition; const std::vector clusters; private: std::vector mEmberClusters; std::vector mDeviceTypes; + std::vector mSemanticTags; EmberAfEndpointType mEmberEndpoint; }; diff --git a/src/app/util/mock/attribute-storage.cpp b/src/app/util/mock/attribute-storage.cpp index 57f3d1e521..f41ba4de69 100644 --- a/src/app/util/mock/attribute-storage.cpp +++ b/src/app/util/mock/attribute-storage.cpp @@ -237,6 +237,39 @@ chip::EndpointId emberAfEndpointFromIndex(uint16_t index) return config.endpoints[index].id; } +namespace chip { +namespace app { + +EndpointComposition GetCompositionForEndpointIndex(uint16_t endpointIndex) +{ + return GetMockNodeConfig().endpoints[endpointIndex].composition; +} + +} // namespace app +} // namespace chip + +EndpointId emberAfParentEndpointFromIndex(uint16_t index) +{ + return kInvalidEndpointId; +} + +CHIP_ERROR GetSemanticTagForEndpointAtIndex(EndpointId endpoint, size_t index, + Clusters::Descriptor::Structs::SemanticTagStruct::Type & tag) +{ + auto ep = GetMockNodeConfig().endpointById(endpoint); + + if (ep) + { + auto semanticTags = ep->semanticTags(); + if (index < semanticTags.size()) + { + tag = semanticTags[index]; + return CHIP_NO_ERROR; + } + } + return CHIP_ERROR_NOT_FOUND; +} + chip::Optional emberAfGetNthClusterId(chip::EndpointId endpointId, uint8_t n, bool server) { VerifyOrReturnValue(server, NullOptional); // only server clusters supported diff --git a/src/controller/tests/data_model/DataModelFixtures.cpp b/src/controller/tests/data_model/DataModelFixtures.cpp index 6f42c38a77..7ef9975bdf 100644 --- a/src/controller/tests/data_model/DataModelFixtures.cpp +++ b/src/controller/tests/data_model/DataModelFixtures.cpp @@ -474,16 +474,21 @@ std::optional CustomDataModel::Invoke(const InvokeRequest & return std::nullopt; // handler status is set by the dispatch } -EndpointId CustomDataModel::FirstEndpoint() +DataModel::EndpointEntry CustomDataModel::FirstEndpoint() { return CodegenDataModelProviderInstance()->FirstEndpoint(); } -EndpointId CustomDataModel::NextEndpoint(EndpointId before) +DataModel::EndpointEntry CustomDataModel::NextEndpoint(EndpointId before) { return CodegenDataModelProviderInstance()->NextEndpoint(before); } +std::optional CustomDataModel::GetEndpointInfo(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->GetEndpointInfo(endpoint); +} + std::optional CustomDataModel::FirstDeviceType(EndpointId endpoint) { return std::nullopt; @@ -495,19 +500,40 @@ std::optional CustomDataModel::NextDeviceType(Endpoi return std::nullopt; } -ClusterEntry CustomDataModel::FirstCluster(EndpointId endpoint) +std::optional CustomDataModel::GetFirstSemanticTag(EndpointId endpoint) +{ + return std::nullopt; +} + +std::optional CustomDataModel::GetNextSemanticTag(EndpointId endpoint, + const SemanticTag & previous) +{ + return std::nullopt; +} + +ClusterEntry CustomDataModel::FirstServerCluster(EndpointId endpoint) +{ + return CodegenDataModelProviderInstance()->FirstServerCluster(endpoint); +} + +ClusterEntry CustomDataModel::NextServerCluster(const ConcreteClusterPath & before) +{ + return CodegenDataModelProviderInstance()->NextServerCluster(before); +} + +std::optional CustomDataModel::GetServerClusterInfo(const ConcreteClusterPath & path) { - return CodegenDataModelProviderInstance()->FirstCluster(endpoint); + return CodegenDataModelProviderInstance()->GetServerClusterInfo(path); } -ClusterEntry CustomDataModel::NextCluster(const ConcreteClusterPath & before) +ConcreteClusterPath CustomDataModel::FirstClientCluster(EndpointId endpoint) { - return CodegenDataModelProviderInstance()->NextCluster(before); + return CodegenDataModelProviderInstance()->FirstClientCluster(endpoint); } -std::optional CustomDataModel::GetClusterInfo(const ConcreteClusterPath & path) +ConcreteClusterPath CustomDataModel::NextClientCluster(const ConcreteClusterPath & before) { - return CodegenDataModelProviderInstance()->GetClusterInfo(path); + return CodegenDataModelProviderInstance()->NextClientCluster(before); } AttributeEntry CustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster) diff --git a/src/controller/tests/data_model/DataModelFixtures.h b/src/controller/tests/data_model/DataModelFixtures.h index e9b32aead6..c8136751c8 100644 --- a/src/controller/tests/data_model/DataModelFixtures.h +++ b/src/controller/tests/data_model/DataModelFixtures.h @@ -122,14 +122,19 @@ class CustomDataModel : public DataModel::Provider std::optional Invoke(const DataModel::InvokeRequest & request, chip::TLV::TLVReader & input_arguments, CommandHandler * handler) override; - EndpointId FirstEndpoint() override; - EndpointId NextEndpoint(EndpointId before) override; + DataModel::EndpointEntry FirstEndpoint() override; + DataModel::EndpointEntry NextEndpoint(EndpointId before) override; + std::optional GetEndpointInfo(EndpointId endpoint) override; std::optional FirstDeviceType(EndpointId endpoint) override; std::optional NextDeviceType(EndpointId endpoint, const DataModel::DeviceTypeEntry & previous) override; - DataModel::ClusterEntry FirstCluster(EndpointId endpoint) override; - DataModel::ClusterEntry NextCluster(const ConcreteClusterPath & before) override; - std::optional GetClusterInfo(const ConcreteClusterPath & path) override; + std::optional GetFirstSemanticTag(EndpointId endpoint) override; + std::optional GetNextSemanticTag(EndpointId endpoint, const SemanticTag & previous) override; + DataModel::ClusterEntry FirstServerCluster(EndpointId endpoint) override; + DataModel::ClusterEntry NextServerCluster(const ConcreteClusterPath & before) override; + std::optional GetServerClusterInfo(const ConcreteClusterPath & path) override; + ConcreteClusterPath FirstClientCluster(EndpointId endpoint) override; + ConcreteClusterPath NextClientCluster(const ConcreteClusterPath & before) override; DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override; DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override; std::optional GetAttributeInfo(const ConcreteAttributePath & path) override; From 99e1006725885be6a298a33f936825db492a3e54 Mon Sep 17 00:00:00 2001 From: Jake Ororke Date: Fri, 29 Nov 2024 07:29:19 -0800 Subject: [PATCH 119/219] Updating TC_CADMIN_1_9 test module due to issues noticed during step 4 (#36546) * Updating TC_CADMIN_1_9 test module: - Replacing wait with using 3 and 50 as error codes possible when attempting to commission on the 21st attempt! * Restyled by autopep8 * Updating TC_CADMIN_1_9 test module: - Attempting to resolve linting error for bare except * Updating TC_CADMIN_1_9 test module: - Attempting to resolve linting errors * Updating CADMIN_1_9 test module: - Replaced exception to using asserts.assert_in() function instead, much cleaner! --------- Co-authored-by: Restyled.io --- src/python_testing/TC_CADMIN_1_9.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/python_testing/TC_CADMIN_1_9.py b/src/python_testing/TC_CADMIN_1_9.py index b3b09afad3..9bad8043d9 100644 --- a/src/python_testing/TC_CADMIN_1_9.py +++ b/src/python_testing/TC_CADMIN_1_9.py @@ -105,7 +105,9 @@ async def CommissionAttempt( errcode = await self.CommissionOnNetwork(setupPinCode) logging.info('Commissioning complete done. Successful? {}, errorcode = {}'.format(errcode.is_success, errcode)) asserts.assert_false(errcode.is_success, 'Commissioning complete did not error as expected') - asserts.assert_true(errcode.sdk_code == expectedErrCode, 'Unexpected error code returned from CommissioningComplete') + # TODO: Adding try or except clause here as the errcode code be either 50 for timeout or 3 for incorrect state at this time + # until issue mentioned in https://github.com/project-chip/connectedhomeip/issues/34383 can be resolved + asserts.assert_in(errcode.sdk_code, [expectedErrCode, 3], 'Unexpected error code returned from CommissioningComplete') def pics_TC_CADMIN_1_9(self) -> list[str]: return ["CADMIN.S"] @@ -127,9 +129,6 @@ async def test_TC_CADMIN_1_9(self): self.step(3) await self.CommissionAttempt(setupPinCode, expectedErrCode=0x03) - # TODO: Found if we don't add sleep time after test completes that we get unexpected error code and response after the 21st iteration. - # Link to Bug Filed: https://github.com/project-chip/connectedhomeip/issues/34383 - sleep(1) self.step(4) await self.CommissionAttempt(setupPinCode, expectedErrCode=0x32) From d37eae17d2fa12645fa354ee99903bc9c8e8bc45 Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Sat, 30 Nov 2024 00:10:08 +0800 Subject: [PATCH 120/219] esp32: remove esp32_codegen.cmake and use common chip_data_model.cmake instead (#36674) --- build/chip/esp32/esp32_codegen.cmake | 77 --------- docs/zap_and_codegen/code_generation.md | 3 - .../esp32/main/CMakeLists.txt | 152 +++++------------- .../esp32/main/CMakeLists.txt | 126 ++++----------- examples/bridge-app/esp32/main/CMakeLists.txt | 50 ++---- examples/chef/esp32/main/CMakeLists.txt | 101 +++++------- .../esp32/main/CMakeLists.txt | 106 ++++-------- .../esp32/main/CMakeLists.txt | 60 ++----- .../lighting-app/esp32/main/CMakeLists.txt | 83 +++------- .../lit-icd-app/esp32/main/CMakeLists.txt | 44 ++--- examples/lock-app/esp32/main/CMakeLists.txt | 123 ++++---------- .../esp32/main/CMakeLists.txt | 56 +++---- .../esp32/main/CMakeLists.txt | 69 +++----- .../esp32/main/CMakeLists.txt | 61 +++---- .../thread-br-app/esp32/main/CMakeLists.txt | 61 ++----- 15 files changed, 321 insertions(+), 851 deletions(-) delete mode 100644 build/chip/esp32/esp32_codegen.cmake diff --git a/build/chip/esp32/esp32_codegen.cmake b/build/chip/esp32/esp32_codegen.cmake deleted file mode 100644 index 9cbd839f10..0000000000 --- a/build/chip/esp32/esp32_codegen.cmake +++ /dev/null @@ -1,77 +0,0 @@ -# -# Copyright (c) 2022 Project CHIP Authors -# All rights reserved. -# -# 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. -# - -macro(chip_app_component_codegen IDL_NAME) - include("${CHIP_ROOT}/build/chip/chip_codegen.cmake") - include("${CHIP_ROOT}/src/app/codegen-data-model-provider/model.cmake") - - # The IDF build system performs a two-pass expansion to determine - # component expansion. The first pass runs in script-mode - # to determine idf_component_register REQUIRES and PRIV_REQUIRES. - # - # We can only set up code generation during the 2nd pass - # - # see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html - if (NOT CMAKE_BUILD_EARLY_EXPANSION) - - chip_codegen(app-codegen - INPUT "${IDL_NAME}" - GENERATOR "cpp-app" - OUTPUTS - "app/PluginApplicationCallbacks.h" - "app/callback-stub.cpp" - "app/cluster-init-callback.cpp" - OUTPUT_PATH APP_GEN_DIR - OUTPUT_FILES APP_GEN_FILES - ) - - add_dependencies(${COMPONENT_LIB} app-codegen) - target_include_directories(${COMPONENT_LIB} PUBLIC "${APP_GEN_DIR}") - target_sources(${COMPONENT_LIB} PRIVATE ${APP_GEN_FILES}) - endif() -endmacro() - -macro(chip_app_component_zapgen ZAP_NAME) - include("${CHIP_ROOT}/build/chip/chip_codegen.cmake") - - # The IDF build system performs a two-pass expansion to determine - # component expansion. The first pass runs in script-mode - # to determine idf_component_register REQUIRES and PRIV_REQUIRES. - # - # We can only set up code generation during the 2nd pass - # - # see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html - if (NOT CMAKE_BUILD_EARLY_EXPANSION) - - chip_zapgen(app-zapgen - INPUT "${ZAP_NAME}" - GENERATOR "app-templates" - OUTPUTS - "zap-generated/access.h" - "zap-generated/endpoint_config.h" - "zap-generated/gen_config.h" - "zap-generated/IMClusterCommandHandler.cpp" - OUTPUT_PATH APP_TEMPLATE_GEN_DIR - OUTPUT_FILES APP_TEMPLATE_GEN_FILES - ) - - add_dependencies(${COMPONENT_LIB} app-zapgen) - target_include_directories(${COMPONENT_LIB} PUBLIC "${APP_TEMPLATE_GEN_DIR}") - target_sources(${COMPONENT_LIB} PRIVATE ${APP_TEMPLATE_GEN_FILES} ${CODEGEN_DATA_MODEL_SOURCES}) - - endif() -endmacro() diff --git a/docs/zap_and_codegen/code_generation.md b/docs/zap_and_codegen/code_generation.md index e6ff51b318..aac74bd6e6 100644 --- a/docs/zap_and_codegen/code_generation.md +++ b/docs/zap_and_codegen/code_generation.md @@ -213,9 +213,6 @@ at: - `src/app/chip_data_model.cmake` - `src/app/chip_data_model.gni` -Additionally, `build/chip/esp32/esp32_codegen.cmake` adds processing support for -the 2-pass cmake builds used by the Espressif `idf.py` build system. - ## Pre-generation Code pre-generation can be used: diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index c35efdf4de..66e0c5b7b2 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -16,111 +16,47 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) # The list of src and include dirs must be in sync with that in all-clusters-app/esp32/main/component.mk -set(PRIV_INCLUDE_DIRS_LIST - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/include" - "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/third_party/nlfaultinjection/include" + +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(ALL_CLUSTERS_COMMON_DIR ${CHIP_ROOT}/examples/all-clusters-app/all-clusters-common REALPATH) +get_filename_component(ENERGY_MANAGEMENT_COMMON_DIR ${CHIP_ROOT}/examples/energy-management-app/energy-management-common/ REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + +set(PRIV_INCLUDE_DIRS_LIST "${ALL_CLUSTERS_COMMON_DIR}/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/common/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/water-heater/include" + "${CMAKE_CURRENT_LIST_DIR}/include" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/third_party/nlfaultinjection/include" ) -set(SRC_DIRS_LIST - "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util/persistence" - "${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/air-quality-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/test-cluster-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/boolean-state-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fault-injection-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fan-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/on-off-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/level-control" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/window-covering-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/color-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-state-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-select-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-base-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/low-power-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thermostat-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thermostat-user-interface-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/scenes-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/smoke-co-alarm-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/refrigerator-alarm-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/icd-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/device-energy-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wake-on-lan-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/pump-configuration-and-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-topology-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/resource-monitoring-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/temperature-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-synchronization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/valve-configuration-and-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/dishwasher-alarm-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-washer-controls-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-washer-controls-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-dryer-controls-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-preference-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-energy-measurement-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-power-measurement-server" +set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${ALL_CLUSTERS_COMMON_DIR}/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/common/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/water-heater/src" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" ) if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" ) if (${IDF_VERSION_MAJOR} LESS 5) @@ -130,26 +66,24 @@ else() endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) endif (CONFIG_ENABLE_PW_RPC) if (CONFIG_ENABLE_ICD_SERVER) - list(APPEND PRIV_INCLUDE_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/icd") - list(APPEND SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/icd") + list(APPEND PRIV_INCLUDE_DIRS_LIST "${CHIP_ROOT}/examples/platform/esp32/icd") + list(APPEND SRC_DIRS_LIST "${CHIP_ROOT}/examples/platform/esp32/icd") endif() idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST}) -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) - -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") - -chip_app_component_codegen("${CHIP_ROOT}/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${ALL_CLUSTERS_COMMON_DIR}/all-clusters-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt index 680d4a9c02..b3f1dc9048 100644 --- a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt @@ -16,96 +16,39 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) -# The list of src and include dirs must be in sync with that in all-clusters-minimal-app/esp32/main/component.mk -set(PRIV_INCLUDE_DIRS_LIST - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include" - "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" + +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(ALL_CLUSTERS_COMMON_DIR ${CHIP_ROOT}/examples/all-clusters-app/all-clusters-common REALPATH) +get_filename_component(ENERGY_MANAGEMENT_COMMON_DIR ${CHIP_ROOT}/examples/energy-management-app/energy-management-common/ REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + +set(PRIV_INCLUDE_DIRS_LIST "${ALL_CLUSTERS_COMMON_DIR}/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/common/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/include" + "${CMAKE_CURRENT_LIST_DIR}/include" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" ) -set(SRC_DIRS_LIST - "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util/persistence" - "${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/application-basic-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/fan-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/on-off-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/level-control" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/account-login-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/application-launcher-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/audio-output-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/window-covering-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/color-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/content-launch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/media-input-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-select-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/low-power-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/keypad-input-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/media-playback-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/target-navigator-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/temperature-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thermostat-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thermostat-user-interface-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/channel-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/scenes-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/smoke-co-alarm-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/device-energy-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wake-on-lan-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/pump-configuration-and-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/resource-monitoring-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src" +set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" + "${CHIP_ROOT}/examples/providers" + "${ALL_CLUSTERS_COMMON_DIR}/src" ) if(CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" ) if(${IDF_VERSION_MAJOR} LESS 5) @@ -115,21 +58,20 @@ if(CONFIG_ENABLE_PW_RPC) endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) endif(CONFIG_ENABLE_PW_RPC) idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST}) -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") - -chip_app_component_codegen("${CHIP_ROOT}/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/bridge-app/esp32/main/CMakeLists.txt b/examples/bridge-app/esp32/main/CMakeLists.txt index 9d34b44a92..de166919f8 100644 --- a/examples/bridge-app/esp32/main/CMakeLists.txt +++ b/examples/bridge-app/esp32/main/CMakeLists.txt @@ -14,49 +14,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${CHIP_ROOT}/examples/providers" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bridged-device-basic-information-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/level-control" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/on-off-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers") - -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) - -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/providers") -chip_app_component_codegen("${CHIP_ROOT}/examples/bridge-app/bridge-common/bridge-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/bridge-app/bridge-common/bridge-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/bridge-app/bridge-common/bridge-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/chef/esp32/main/CMakeLists.txt b/examples/chef/esp32/main/CMakeLists.txt index a7905ff214..23ec53f0f8 100644 --- a/examples/chef/esp32/main/CMakeLists.txt +++ b/examples/chef/esp32/main/CMakeLists.txt @@ -16,71 +16,45 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) -get_filename_component(CHIP_ROOT ../third_party/connectedhomeip REALPATH) -get_filename_component(CHEF ${CMAKE_CURRENT_SOURCE_DIR}/../../ REALPATH) +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(CHEF ${CHIP_ROOT}/examples/chef REALPATH) # include(${CMAKE_CURRENT_LIST_DIR}/../../project_include.cmake) # message(STATUS "Product ID " ${CONFIG_DEVICE_PRODUCT_ID}) # message(STATUS "Vendor ID " ${CONFIG_DEVICE_VENDOR_ID}) -set(CHIP_SHELL_DIR "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/shell") +set(CHIP_SHELL_DIR "${CHIP_ROOT}/examples/shell") set(PRIV_INCLUDE_DIRS_LIST - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/third_party/nlio/repo/include" - "${CMAKE_SOURCE_DIR}/../" - "${CMAKE_SOURCE_DIR}/../common" - "${CMAKE_SOURCE_DIR}/../common/clusters" + "${CHIP_ROOT}/zzz_generated/" + "${CHIP_ROOT}/zzz_generated/app-common" + "${CHIP_ROOT}/examples/platform/esp32/" + "${CHIP_ROOT}/third_party/nlio/repo/include" + "${CHEF}" + "${CHEF}/common" + "${CHEF}/common/clusters" "${CMAKE_SOURCE_DIR}/main/include/" ) - -# find_package(Python3 REQUIRED) -set(ZAP_FILE ${CMAKE_CURRENT_LIST_DIR}/../../devices/${SAMPLE_NAME}.zap) -execute_process( - COMMAND ${Python3_EXECUTABLE} ${CHIP_ROOT}/src/app/zap_cluster_list.py --zap_file ${ZAP_FILE} - OUTPUT_VARIABLE CLUSTER_LIST - ERROR_VARIABLE ERROR_MESSAGE - RESULT_VARIABLE RC -) -# if (NOT RC EQUAL 0) -# message(FATAL_ERROR "Failed to execute zap_cluster_list.py: ${ERROR_MESSAGE}") -# endif() - -message(STATUS "** Start of Cluster List **") -string(REPLACE "\n" ";" CLUSTER_LIST "${CLUSTER_LIST}") -foreach(CLUSTER ${CLUSTER_LIST}) - set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CHIP_ROOT}/src/app/clusters/${CLUSTER}") - message(STATUS "src/app/clusters/${CLUSTER}") -endforeach() -message(STATUS "** End of Cluster List **") - set(SRC_DIRS_LIST ${SRC_DIRS_LIST} "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/../common" - "${CMAKE_SOURCE_DIR}/../common/clusters/audio-output/" - "${CMAKE_SOURCE_DIR}/../common/clusters/channel/" - "${CMAKE_SOURCE_DIR}/../common/clusters/door-lock/" - "${CMAKE_SOURCE_DIR}/../common/clusters/keypad-input/" - "${CMAKE_SOURCE_DIR}/../common/clusters/low-power/" - "${CMAKE_SOURCE_DIR}/../common/clusters/media-input/" - "${CMAKE_SOURCE_DIR}/../common/clusters/media-playback/" - "${CMAKE_SOURCE_DIR}/../common/clusters/refrigerator-and-temperature-controlled-cabinet-mode/" - "${CMAKE_SOURCE_DIR}/../common/clusters/resource-monitoring/" - "${CMAKE_SOURCE_DIR}/../common/clusters/switch/" - "${CMAKE_SOURCE_DIR}/../common/clusters/target-navigator/" - "${CMAKE_SOURCE_DIR}/../common/clusters/temperature-control/" - "${CMAKE_SOURCE_DIR}/../common/clusters/wake-on-lan/" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" + "${CHEF}/common" + "${CHEF}/common/clusters/audio-output/" + "${CHEF}/common/clusters/channel/" + "${CHEF}/common/clusters/door-lock/" + "${CHEF}/common/clusters/keypad-input/" + "${CHEF}/common/clusters/low-power/" + "${CHEF}/common/clusters/media-input/" + "${CHEF}/common/clusters/media-playback/" + "${CHEF}/common/clusters/refrigerator-and-temperature-controlled-cabinet-mode/" + "${CHEF}/common/clusters/resource-monitoring/" + "${CHEF}/common/clusters/switch/" + "${CHEF}/common/clusters/target-navigator/" + "${CHEF}/common/clusters/temperature-control/" + "${CHEF}/common/clusters/wake-on-lan/" + "${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated/attributes" ) if (CONFIG_ENABLE_CHIP_SHELL) @@ -94,12 +68,12 @@ endif() if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/../../platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/../../common" - "${CMAKE_SOURCE_DIR}/../../common/pigweed" - "${CMAKE_SOURCE_DIR}/../../common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/../../common/screen-framework/include/" - "${CMAKE_SOURCE_DIR}/../../../src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/common/screen-framework/include/" + "${CHIP_ROOT}/src/lib/support" ) if (${IDF_VERSION_MAJOR} LESS 5) @@ -109,9 +83,9 @@ else() endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/../../platform/esp32" - "${CMAKE_SOURCE_DIR}/../../common/pigweed" - "${CMAKE_SOURCE_DIR}/../../common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) else() set(SRC_DIRS_LIST @@ -128,9 +102,10 @@ idf_component_register(PRIV_INCLUDE_DIRS # Forces the linker to include common/stubs.cpp target_link_libraries(${COMPONENT_LIB} INTERFACE "-u chef_include_stubs_impl") -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHEF}/devices/${SAMPLE_NAME}.matter") -chip_app_component_zapgen("${CHEF}/devices/${SAMPLE_NAME}.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHEF}/devices/${SAMPLE_NAME}.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index 06623d3faf..5b42273f62 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -16,79 +16,44 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(ENERGY_MANAGEMENT_COMMON_DIR ${CHIP_ROOT}/examples/energy-management-app/energy-management-common/ REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + set(PRIV_INCLUDE_DIRS_LIST - "${APP_GEN_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/esp32/main/include" + "${CHIP_ROOT}/examples/providers" + "${ENERGY_MANAGEMENT_COMMON_DIR}/common/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/include" + "${ENERGY_MANAGEMENT_COMMON_DIR}/water-heater/include" "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" + "${CHIP_ROOT}/examples/platform/esp32" ) set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/common/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/time" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/device-energy-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-topology-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-base-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-energy-measurement-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-power-measurement-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/water-heater-management-server" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/providers" + "${ENERGY_MANAGEMENT_COMMON_DIR}/common/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/device-energy-management/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-evse/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/energy-reporting/src" + "${ENERGY_MANAGEMENT_COMMON_DIR}/water-heater/src" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/time" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" ) if(CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" ) if(${IDF_VERSION_MAJOR} LESS 5) @@ -98,20 +63,19 @@ if(CONFIG_ENABLE_PW_RPC) endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) endif(CONFIG_ENABLE_PW_RPC) idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST}) -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") - -chip_app_component_codegen("${CHIP_ROOT}/examples/energy-management-app/energy-management-common/energy-management-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/energy-management-app/energy-management-common/energy-management-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${ENERGY_MANAGEMENT_COMMON_DIR}/energy-management-app.zap +) if(CONFIG_ENABLE_ESP_INSIGHTS_TRACE) target_add_binary_data(${COMPONENT_TARGET} "insights_auth_key.txt" TEXT) diff --git a/examples/light-switch-app/esp32/main/CMakeLists.txt b/examples/light-switch-app/esp32/main/CMakeLists.txt index 92be83565a..1f3279159f 100644 --- a/examples/light-switch-app/esp32/main/CMakeLists.txt +++ b/examples/light-switch-app/esp32/main/CMakeLists.txt @@ -16,57 +16,31 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-synchronization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/icd-management-server") + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" +) get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHIP_ROOT}/examples/light-switch-app/light-switch-common/light-switch-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/light-switch-app/light-switch-common/light-switch-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/light-switch-app/light-switch-common/light-switch-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/lighting-app/esp32/main/CMakeLists.txt b/examples/lighting-app/esp32/main/CMakeLists.txt index 1ad5bc1aa3..1fbda23c0f 100644 --- a/examples/lighting-app/esp32/main/CMakeLists.txt +++ b/examples/lighting-app/esp32/main/CMakeLists.txt @@ -16,65 +16,35 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(LIGHT_COMMON_DIR ${CHIP_ROOT}/examples/lighting-app/lighting-common REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + set(PRIV_INCLUDE_DIRS_LIST - "${APP_GEN_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/lighting-app/lighting-common/include" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" + "${LIGHT_COMMON_DIR}/include" "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" ) set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/lighting-app/lighting-common/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/color-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/level-control" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/on-off-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/scenes-server" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${LIGHT_COMMON_DIR}/src" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" ) if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" ) if (${IDF_VERSION_MAJOR} LESS 5) @@ -84,20 +54,19 @@ else() endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) endif (CONFIG_ENABLE_PW_RPC) idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST}) -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") - -chip_app_component_codegen("${CHIP_ROOT}/examples/lighting-app/lighting-common/lighting-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/lighting-app/lighting-common/lighting-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${LIGHT_COMMON_DIR}/lighting-app.zap +) if (CONFIG_ENABLE_ESP_INSIGHTS_TRACE) target_add_binary_data(${COMPONENT_TARGET} "insights_auth_key.txt" TEXT) diff --git a/examples/lit-icd-app/esp32/main/CMakeLists.txt b/examples/lit-icd-app/esp32/main/CMakeLists.txt index 4d8fe2ab4b..322c01d918 100644 --- a/examples/lit-icd-app/esp32/main/CMakeLists.txt +++ b/examples/lit-icd-app/esp32/main/CMakeLists.txt @@ -17,50 +17,28 @@ # get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) set(PRIV_INCLUDE_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/providers" ) set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/icd-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/providers" ) idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST}) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHIP_ROOT}/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/lit-icd-app/lit-icd-common/lit-icd-server-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/lock-app/esp32/main/CMakeLists.txt b/examples/lock-app/esp32/main/CMakeLists.txt index 028a92ae8d..c689f821a3 100644 --- a/examples/lock-app/esp32/main/CMakeLists.txt +++ b/examples/lock-app/esp32/main/CMakeLists.txt @@ -17,6 +17,7 @@ # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) if (CONFIG_ENABLE_PW_RPC) @@ -28,56 +29,27 @@ endif() idf_component_register(INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/lock" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/platform/esp32/lock" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" "${CMAKE_CURRENT_LIST_DIR}/include" "${freertos_include_path}" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/icd-management-server") - -add_dependencies(${COMPONENT_LIB} app-codegen) + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/lock" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" +) set(PIGWEED_ROOT "${CHIP_ROOT}/third_party/pigweed/repo") include(${PIGWEED_ROOT}/pw_build/pigweed.cmake) @@ -152,50 +124,17 @@ target_compile_options(${COMPONENT_LIB} PRIVATE else (CONFIG_ENABLE_PW_RPC) idf_component_register(PRIV_INCLUDE_DIRS - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${CHIP_ROOT}/examples/providers" "${CMAKE_CURRENT_LIST_DIR}/include" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/icd-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/lock" - PRIV_REQUIRES chip QRCode bt nvs_flash driver) - -add_dependencies(${COMPONENT_LIB} app-codegen) + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/lock" +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") @@ -205,9 +144,7 @@ target_compile_options(${COMPONENT_LIB} PUBLIC endif (CONFIG_ENABLE_PW_RPC) -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) - -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") - -chip_app_component_codegen("${CHIP_ROOT}/examples/lock-app/lock-common/lock-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/lock-app/lock-common/lock-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/lock-app/lock-common/lock-app.zap +) diff --git a/examples/ota-provider-app/esp32/main/CMakeLists.txt b/examples/ota-provider-app/esp32/main/CMakeLists.txt index d651ac7706..91ffd50150 100644 --- a/examples/ota-provider-app/esp32/main/CMakeLists.txt +++ b/examples/ota-provider-app/esp32/main/CMakeLists.txt @@ -16,50 +16,30 @@ # # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${CHIP_ROOT}/examples/ota-provider-app" + "${CHIP_ROOT}/examples/providers" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-provider" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/ota-provider-app/ota-provider-common" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/providers" EXCLUDE_SRCS - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp") + "${CHIP_ROOT}/examples/ota-provider-app/ota-provider-common/BdxOtaSender.cpp") -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHIP_ROOT}/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/ota-provider-app/ota-provider-common/ota-provider-app.zap") + +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/ota-provider-app/ota-provider-common/ota-provider-app.zap +) spiffs_create_partition_image(img_storage ${CMAKE_SOURCE_DIR}/spiffs_image FLASH_IN_PROJECT) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) diff --git a/examples/ota-requestor-app/esp32/main/CMakeLists.txt b/examples/ota-requestor-app/esp32/main/CMakeLists.txt index 2688fea497..02cdb91b1c 100644 --- a/examples/ota-requestor-app/esp32/main/CMakeLists.txt +++ b/examples/ota-requestor-app/esp32/main/CMakeLists.txt @@ -17,60 +17,32 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) set(PRIV_INCLUDE_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/providers" ) set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/on-off-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/providers" ) if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" ) if (${IDF_VERSION_MAJOR} LESS 5) @@ -80,18 +52,19 @@ else() endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) endif (CONFIG_ENABLE_PW_RPC) idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST}) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHIP_ROOT}/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt index 8036700df6..ff3464dc37 100644 --- a/examples/temperature-measurement-app/esp32/main/CMakeLists.txt +++ b/examples/temperature-measurement-app/esp32/main/CMakeLists.txt @@ -17,53 +17,29 @@ # get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) set(PRIV_INCLUDE_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/providers" ) set(SRC_DIRS_LIST "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/providers" ) if (CONFIG_ENABLE_PW_RPC) # Append additional directories for RPC build set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/pw_sys_io/public" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/lib/support" + "${CHIP_ROOT}/examples/platform/esp32/pw_sys_io/public" + "${CHIP_ROOT}/examples/common" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" + "${CHIP_ROOT}/src/lib/support" ) if (${IDF_VERSION_MAJOR} LESS 5) @@ -73,9 +49,9 @@ else() endif() set(SRC_DIRS_LIST "${SRC_DIRS_LIST}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/common/pigweed/esp32" + "${CHIP_ROOT}/examples/platform/esp32" + "${CHIP_ROOT}/examples/common/pigweed" + "${CHIP_ROOT}/examples/common/pigweed/esp32" ) endif (CONFIG_ENABLE_PW_RPC) @@ -83,9 +59,10 @@ idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST} SRC_DIRS ${SRC_DIRS_LIST} EMBED_FILES diagnostic_logs/end_user_support.log diagnostic_logs/network_diag.log) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHIP_ROOT}/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") diff --git a/examples/thread-br-app/esp32/main/CMakeLists.txt b/examples/thread-br-app/esp32/main/CMakeLists.txt index c1f82285e4..fd00336b86 100644 --- a/examples/thread-br-app/esp32/main/CMakeLists.txt +++ b/examples/thread-br-app/esp32/main/CMakeLists.txt @@ -16,56 +16,29 @@ # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) +get_filename_component(APP_COMMON_GEN_DIR ${CHIP_ROOT}/zzz_generated/app-common/app-common/zap-generated REALPATH) + idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32" SRC_DIRS "${CMAKE_CURRENT_LIST_DIR}" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated/attributes" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/zzz_generated/app-common/app-common/zap-generated" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension" - "${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/util/persistence" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/access-control-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/administrator-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic-information" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/descriptor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/fixed-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-commissioning-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/general-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/identify-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-border-router-management-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" - "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-synchronization-server") - -get_filename_component(CHIP_ROOT ${CMAKE_SOURCE_DIR}/third_party/connectedhomeip REALPATH) + "${APP_COMMON_GEN_DIR}/attributes" + "${APP_COMMON_GEN_DIR}" + "${CHIP_ROOT}/examples/providers" + "${CHIP_ROOT}/examples/platform/esp32/ota" + "${CHIP_ROOT}/examples/platform/esp32/common" + "${CHIP_ROOT}/examples/platform/esp32/shell_extension" +) -include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake") -chip_app_component_codegen("${CHIP_ROOT}/examples/thread-br-app/thread-br-common/thread-br-app.matter") -chip_app_component_zapgen("${CHIP_ROOT}/examples/thread-br-app/thread-br-common/thread-br-app.zap") +include(${CHIP_ROOT}/src/app/chip_data_model.cmake) +chip_configure_data_model(${COMPONENT_LIB} + ZAP_FILE ${CHIP_ROOT}/examples/thread-br-app/thread-br-common/thread-br-app.zap +) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H") From 2474fc3840ee2aaea703996889b8cf7caeb2cbdc Mon Sep 17 00:00:00 2001 From: C Freeman Date: Fri, 29 Nov 2024 12:04:49 -0500 Subject: [PATCH 121/219] Bridge: Remove ACL client (#36677) --- .../bridge-common/bridge-app.matter | 126 ------------------ .../bridge-app/bridge-common/bridge-app.zap | 28 ++-- 2 files changed, 13 insertions(+), 141 deletions(-) diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 6241e8c635..5979751c01 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -667,131 +667,6 @@ cluster AccessControl = 31 { fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; } -/** The Access Control Cluster exposes a data model view of a - Node's Access Control List (ACL), which codifies the rules used to manage - and enforce Access Control for the Node's endpoints and their associated - cluster instances. */ -cluster AccessControl = 31 { - revision 2; - - enum AccessControlEntryAuthModeEnum : enum8 { - kPASE = 1; - kCASE = 2; - kGroup = 3; - } - - enum AccessControlEntryPrivilegeEnum : enum8 { - kView = 1; - kProxyView = 2; - kOperate = 3; - kManage = 4; - kAdminister = 5; - } - - enum AccessRestrictionTypeEnum : enum8 { - kAttributeAccessForbidden = 0; - kAttributeWriteForbidden = 1; - kCommandForbidden = 2; - kEventForbidden = 3; - } - - enum ChangeTypeEnum : enum8 { - kChanged = 0; - kAdded = 1; - kRemoved = 2; - } - - bitmap Feature : bitmap32 { - kExtension = 0x1; - kManagedDevice = 0x2; - } - - struct AccessRestrictionStruct { - AccessRestrictionTypeEnum type = 0; - nullable int32u id = 1; - } - - struct CommissioningAccessRestrictionEntryStruct { - endpoint_no endpoint = 0; - cluster_id cluster = 1; - AccessRestrictionStruct restrictions[] = 2; - } - - fabric_scoped struct AccessRestrictionEntryStruct { - fabric_sensitive endpoint_no endpoint = 0; - fabric_sensitive cluster_id cluster = 1; - fabric_sensitive AccessRestrictionStruct restrictions[] = 2; - fabric_idx fabricIndex = 254; - } - - struct AccessControlTargetStruct { - nullable cluster_id cluster = 0; - nullable endpoint_no endpoint = 1; - nullable devtype_id deviceType = 2; - } - - fabric_scoped struct AccessControlEntryStruct { - fabric_sensitive AccessControlEntryPrivilegeEnum privilege = 1; - fabric_sensitive AccessControlEntryAuthModeEnum authMode = 2; - nullable fabric_sensitive int64u subjects[] = 3; - nullable fabric_sensitive AccessControlTargetStruct targets[] = 4; - fabric_idx fabricIndex = 254; - } - - fabric_scoped struct AccessControlExtensionStruct { - fabric_sensitive octet_string<128> data = 1; - fabric_idx fabricIndex = 254; - } - - fabric_sensitive info event access(read: administer) AccessControlEntryChanged = 0 { - nullable node_id adminNodeID = 1; - nullable int16u adminPasscodeID = 2; - ChangeTypeEnum changeType = 3; - nullable AccessControlEntryStruct latestValue = 4; - fabric_idx fabricIndex = 254; - } - - fabric_sensitive info event access(read: administer) AccessControlExtensionChanged = 1 { - nullable node_id adminNodeID = 1; - nullable int16u adminPasscodeID = 2; - ChangeTypeEnum changeType = 3; - nullable AccessControlExtensionStruct latestValue = 4; - fabric_idx fabricIndex = 254; - } - - fabric_sensitive info event access(read: administer) FabricRestrictionReviewUpdate = 2 { - int64u token = 0; - optional long_char_string instruction = 1; - optional long_char_string ARLRequestFlowUrl = 2; - fabric_idx fabricIndex = 254; - } - - attribute access(read: administer, write: administer) AccessControlEntryStruct acl[] = 0; - attribute access(read: administer, write: administer) optional AccessControlExtensionStruct extension[] = 1; - readonly attribute int16u subjectsPerAccessControlEntry = 2; - readonly attribute int16u targetsPerAccessControlEntry = 3; - readonly attribute int16u accessControlEntriesPerFabric = 4; - readonly attribute optional CommissioningAccessRestrictionEntryStruct commissioningARL[] = 5; - readonly attribute optional AccessRestrictionEntryStruct arl[] = 6; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; - - request struct ReviewFabricRestrictionsRequest { - CommissioningAccessRestrictionEntryStruct arl[] = 0; - } - - response struct ReviewFabricRestrictionsResponse = 1 { - int64u token = 0; - } - - /** This command signals to the service associated with the device vendor that the fabric administrator would like a review of the current restrictions on the accessing fabric. */ - fabric command access(invoke: administer) ReviewFabricRestrictions(ReviewFabricRestrictionsRequest): ReviewFabricRestrictionsResponse = 0; -} - /** This cluster provides a standardized way for a Node (typically a Bridge, but could be any Node) to expose action information. */ cluster Actions = 37 { revision 1; // NOTE: Default/not specifically set @@ -2272,7 +2147,6 @@ cluster TemperatureMeasurement = 1026 { endpoint 0 { device type ma_rootdevice = 22, version 1; - binding cluster AccessControl; server cluster Descriptor { callback attribute deviceTypeList; diff --git a/examples/bridge-app/bridge-common/bridge-app.zap b/examples/bridge-app/bridge-common/bridge-app.zap index bf78875444..8c5882fbd4 100644 --- a/examples/bridge-app/bridge-common/bridge-app.zap +++ b/examples/bridge-app/bridge-common/bridge-app.zap @@ -1,6 +1,6 @@ { "fileFormat": 2, - "featureLevel": 103, + "featureLevel": 104, "creator": "zap", "keyValuePairs": [ { @@ -41,14 +41,16 @@ "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 22, "profileId": 259, "label": "MA-rootdevice", - "name": "MA-rootdevice" + "name": "MA-rootdevice", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -215,14 +217,6 @@ } ] }, - { - "name": "Access Control", - "code": 31, - "mfgCode": null, - "define": "ACCESS_CONTROL_CLUSTER", - "side": "client", - "enabled": 1 - }, { "name": "Access Control", "code": 31, @@ -4403,14 +4397,16 @@ "code": 14, "profileId": 259, "label": "MA-aggregator", - "name": "MA-aggregator" + "name": "MA-aggregator", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 14, "profileId": 259, "label": "MA-aggregator", - "name": "MA-aggregator" + "name": "MA-aggregator", + "deviceTypeOrder": 0 } ], "deviceVersions": [ @@ -4891,14 +4887,16 @@ "code": 257, "profileId": 259, "label": "MA-dimmablelight", - "name": "MA-dimmablelight" + "name": "MA-dimmablelight", + "deviceTypeOrder": 0 }, "deviceTypes": [ { "code": 257, "profileId": 259, "label": "MA-dimmablelight", - "name": "MA-dimmablelight" + "name": "MA-dimmablelight", + "deviceTypeOrder": 0 } ], "deviceVersions": [ From e402b96fff27361cb46e581d5e84f1971302a35b Mon Sep 17 00:00:00 2001 From: achaulk-goog <107196446+achaulk-goog@users.noreply.github.com> Date: Fri, 29 Nov 2024 17:07:04 -0500 Subject: [PATCH 122/219] Fix JniReferences::GetOptionalValue (#36682) * Fix JniReferences::GetOptionalValue It's possible the optional is not of class java/util/Optional so just use the object provided * fix formatting --- src/lib/support/JniReferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/support/JniReferences.cpp b/src/lib/support/JniReferences.cpp index 021f13c2fb..3e1c8bd79b 100644 --- a/src/lib/support/JniReferences.cpp +++ b/src/lib/support/JniReferences.cpp @@ -310,8 +310,8 @@ CHIP_ERROR JniReferences::GetOptionalValue(jobject optionalObj, jobject & option { JNIEnv * env = GetEnvForCurrentThread(); VerifyOrReturnError(env != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); - jclass optionalCls = nullptr; - ReturnErrorOnFailure(chip::JniReferences::GetInstance().GetLocalClassRef(env, "java/util/Optional", optionalCls)); + VerifyOrReturnError(optionalObj != nullptr, CHIP_JNI_ERROR_NULL_OBJECT); + jclass optionalCls = env->GetObjectClass(optionalObj); jmethodID isPresentMethod = env->GetMethodID(optionalCls, "isPresent", "()Z"); VerifyOrReturnError(isPresentMethod != nullptr, CHIP_JNI_ERROR_METHOD_NOT_FOUND); jboolean isPresent = optionalObj && env->CallBooleanMethod(optionalObj, isPresentMethod); From f488ad44fda5d0fdcefb27894bab9fb58179d8e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 2 Dec 2024 14:55:22 +0100 Subject: [PATCH 123/219] Update host.py to fix water-leak-detector-app gen (#36683) --- scripts/build/builders/host.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index 43b95b7632..7fe5823f37 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -159,7 +159,7 @@ def ExamplePath(self): elif self == HostApp.ENERGY_MANAGEMENT: return 'energy-management-app/linux' elif self == HostApp.WATER_LEAK_DETECTOR: - return 'water-leak-detector/linux' + return 'water-leak-detector-app/linux' else: raise Exception('Unknown app type: %r' % self) From 5ca422b0c8f00c2d385b38e0ad68745bd9b171a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20BOU=C3=89?= Date: Mon, 2 Dec 2024 15:34:16 +0100 Subject: [PATCH 124/219] Formatting code extracts (#36670) * Formatting code extracts Formatting code extracts * Update python.md WARNING: Could not lex literal_block as "python" --- docs/testing/python.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/testing/python.md b/docs/testing/python.md index 1db6ff779b..a7bec6d07e 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -217,7 +217,7 @@ Each `Clusters..Structs.` has: Example: -``` +```python Clusters.BasicInformation.Structs.ProductAppearanceStruct( finish=Clusters.BasicInformation.Enums.ProductFinishEnum.kFabric, primaryColor=Clusters.BasicInformation.Enums.ColorEnum.kBlack) @@ -293,7 +293,7 @@ Multi-path Example: -``` +```python urgent = 1 await dev_ctrl ReadEvent(node_id, [(1, @@ -359,7 +359,7 @@ asserts.assert_equal(ret[0].status, Status.Success, “write failed”) Example: -``` +```python pai = await dev_ctrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.CertificateChainRequest(2)) ``` @@ -387,7 +387,7 @@ class provides some helpers for Mobly integration. use as: -``` +```python if __name__ == "__main__": default_matter_test_main() ``` @@ -479,7 +479,7 @@ See To create a controller on a new fabric: -``` +```python new_CA = self.certificate_authority_manager.NewCertificateAuthority() new_fabric_admin = new_certificate_authority.NewFabricAdmin(vendorId=0xFFF1, @@ -490,7 +490,7 @@ TH2 = new_fabric_admin.NewController(nodeId=112233) Open a commissioning window (ECW): -``` +```python params = self.OpenCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.dut_node_id) ``` @@ -499,7 +499,7 @@ the fabric admin. Fabric admin for default controller: -``` +```python fa = self.certificate_authority_manager.activeCaList[0].adminList[0] second_ctrl = fa.new_fabric_admin.NewController(nodeId=node_id) ``` @@ -577,13 +577,13 @@ running. To compile and install the wheel, do the following: First activate the matter environment using either -``` +```shell . ./scripts/bootstrap.sh ``` or -``` +```shell . ./scripts/activate.sh ``` @@ -592,7 +592,7 @@ subsequent setups as it is faster. Next build the python wheels and create / activate a venv -``` +```shell ./scripts/build_python.sh -i out/python_env source out/python_env/bin/activate ``` @@ -609,7 +609,7 @@ that will be commissioned either over BLE or WiFi. For example, to run the TC-ACE-1.2 tests against an un-commissioned DUT: -``` +```shell python3 src/python_testing/TC_ACE_1_2.py --commissioning-method on-network --qr-code MT:-24J0AFN00KA0648G00 ``` @@ -617,7 +617,7 @@ Some tests require additional arguments (ex. PIXITs or configuration variables for the CI). These arguments can be passed as sets of key/value pairs using the `---arg:` command line arguments. For example: -``` +```shell --int-arg PIXIT.ACE.APPENDPOINT:1 --int-arg PIXIT.ACE.APPDEVTYPEID:0x0100 --string-arg PIXIT.ACE.APPCLUSTER:OnOff --string-arg PIXIT.ACE.APPATTRIBUTE:OnOff ``` From 511997770172f01067288d16625daa506af2ea2a Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Mon, 2 Dec 2024 23:58:25 +0900 Subject: [PATCH 125/219] Documentation: Fix incorrect paths in fuzz_testing.md and yaml.md (#36689) * Documentation: Fix incorrect paths in fuzz_testing.md and yaml.md * Update fuzz_testing.md --- docs/testing/fuzz_testing.md | 4 ++-- docs/testing/yaml.md | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/testing/fuzz_testing.md b/docs/testing/fuzz_testing.md index 68f08f4885..7b5fd5683f 100644 --- a/docs/testing/fuzz_testing.md +++ b/docs/testing/fuzz_testing.md @@ -79,10 +79,10 @@ for an example of a simple fuzz test. - Another example: [src/setup_payload/tests/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/b367512f519e5e109346e81a0d84fd85cd9192f7/src/setup_payload/tests/BUILD.gn#L43) -- Add to `src/BUILD.gn` +- Add to `${chip_root}/BUILD.gn` - Add the Fuzzing Target in this part of the code : - [src/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/b367512f519e5e109346e81a0d84fd85cd9192f7/BUILD.gn#L52) + [\${chip_root}/BUILD.gn](https://github.com/project-chip/connectedhomeip/blob/b367512f519e5e109346e81a0d84fd85cd9192f7/BUILD.gn#L52) - Add Fuzzing Target like that diff --git a/docs/testing/yaml.md b/docs/testing/yaml.md index e3736d6272..0adeca43e5 100644 --- a/docs/testing/yaml.md +++ b/docs/testing/yaml.md @@ -330,12 +330,11 @@ or bootstrap.sh should be used for for the first setup, activate.sh may be used for subsequent setups as it is faster. -Next build the python wheels and create a venv (called `py` here, but any name -may be used) +Next build the python wheels and create a venv ``` ./scripts/build_python.sh -i out/python_env -source py/bin/activate +source out/python_env/bin/activate ``` Compile chip-tool: From e7b0989a96e7c9d93fab6cad93d658754aaafc02 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Mon, 2 Dec 2024 16:03:41 +0100 Subject: [PATCH 126/219] Stop shell read loop if the input stream was closed (#36675) --- src/lib/shell/MainLoopDefault.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/shell/MainLoopDefault.cpp b/src/lib/shell/MainLoopDefault.cpp index 6a3a6b300b..30e748836b 100644 --- a/src/lib/shell/MainLoopDefault.cpp +++ b/src/lib/shell/MainLoopDefault.cpp @@ -57,6 +57,15 @@ size_t ReadLine(char * buffer, size_t max) break; } + // Stop the loop if the input stream is closed. + if (ret == 0) + { + if (line_sz > 0) + // Return current buffer if it is not empty. + buffer[line_sz++] = '\0'; + break; + } + if (ret != 1) continue; From 4c69001a0acef9a77c5963708ecc67262c2b26bd Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Tue, 3 Dec 2024 00:26:18 +0900 Subject: [PATCH 127/219] Ensure SYSTEM_STATS_INCREMENT only on successful Timer allocation in SystemTimer.h (#36690) * Fix: Ensure SYSTEM_STATS_INCREMENT only on successful Timer allocation * Update SystemTimer.h --- src/system/SystemTimer.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/system/SystemTimer.h b/src/system/SystemTimer.h index 698be028ce..99c3d8620f 100644 --- a/src/system/SystemTimer.h +++ b/src/system/SystemTimer.h @@ -204,7 +204,11 @@ class TimerPool Timer * Create(Layer & systemLayer, System::Clock::Timestamp awakenTime, TimerCompleteCallback onComplete, void * appState) { Timer * timer = mTimerPool.CreateObject(systemLayer, awakenTime, onComplete, appState); - SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers); + if (timer != nullptr) + { + SYSTEM_STATS_INCREMENT(Stats::kSystemLayer_NumTimers); + } + return timer; } From a3a443a7d15552d133f8ddb7b1ffd6d10496b081 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Mon, 2 Dec 2024 13:58:35 -0500 Subject: [PATCH 128/219] Disable chef build of tempcontrol cabinet. (#36694) --- .../temperature-control/static-supported-temperature-levels.cpp | 1 + integrations/cloudbuild/chef.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp b/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp index 045825d8fa..7ebbd0f813 100644 --- a/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp +++ b/examples/chef/common/clusters/temperature-control/static-supported-temperature-levels.cpp @@ -21,6 +21,7 @@ #ifdef MATTER_DM_PLUGIN_TEMPERATURE_CONTROL_SERVER #include "static-supported-temperature-levels.h" #include +#include using namespace chip; using namespace chip::app::Clusters; diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index 238b47b0fc..fd8543ee2d 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -29,7 +29,7 @@ steps: args: - >- perl -i -pe 's/^gdbgui==/# gdbgui==/' /opt/espressif/esp-idf/requirements.txt && - ./examples/chef/chef.py --build_all --build_exclude noip + ./examples/chef/chef.py --build_all --build_exclude "noip|temperaturecontrolledcabinet" id: CompileAll waitFor: - Bootstrap From 2bc325178516defcf6706e5df793af1b55645fe1 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Tue, 3 Dec 2024 02:49:58 -0500 Subject: [PATCH 129/219] Bridge app: remove binding client (#36697) A binding client means that this device would be reaching out and writing to the binding cluster on another endpoint, which is likely NOT what was intended here since it doesn't do that. The current app now shows no clusters listed in the client list on any cluster (from device dump). --- .../bridge-common/bridge-app.matter | 22 ------------------- .../bridge-app/bridge-common/bridge-app.zap | 8 ------- 2 files changed, 30 deletions(-) diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter index 5979751c01..26a1662274 100644 --- a/examples/bridge-app/bridge-common/bridge-app.matter +++ b/examples/bridge-app/bridge-common/bridge-app.matter @@ -521,27 +521,6 @@ cluster Descriptor = 29 { readonly attribute int16u clusterRevision = 65533; } -/** The Binding Cluster is meant to replace the support from the Zigbee Device Object (ZDO) for supporting the binding table. */ -cluster Binding = 30 { - revision 1; // NOTE: Default/not specifically set - - fabric_scoped struct TargetStruct { - optional node_id node = 1; - optional group_id group = 2; - optional endpoint_no endpoint = 3; - optional cluster_id cluster = 4; - fabric_idx fabricIndex = 254; - } - - attribute access(write: manage) TargetStruct binding[] = 0; - readonly attribute command_id generatedCommandList[] = 65528; - readonly attribute command_id acceptedCommandList[] = 65529; - readonly attribute event_id eventList[] = 65530; - readonly attribute attrib_id attributeList[] = 65531; - readonly attribute bitmap32 featureMap = 65532; - readonly attribute int16u clusterRevision = 65533; -} - /** The Access Control Cluster exposes a data model view of a Node's Access Control List (ACL), which codifies the rules used to manage and enforce Access Control for the Node's endpoints and their associated @@ -2496,7 +2475,6 @@ endpoint 0 { endpoint 1 { device type ma_aggregator = 14, version 1; - binding cluster Binding; server cluster Identify { ram attribute identifyTime default = 0x0; diff --git a/examples/bridge-app/bridge-common/bridge-app.zap b/examples/bridge-app/bridge-common/bridge-app.zap index 8c5882fbd4..3dc8efff76 100644 --- a/examples/bridge-app/bridge-common/bridge-app.zap +++ b/examples/bridge-app/bridge-common/bridge-app.zap @@ -4713,14 +4713,6 @@ } ] }, - { - "name": "Binding", - "code": 30, - "mfgCode": null, - "define": "BINDING_CLUSTER", - "side": "client", - "enabled": 1 - }, { "name": "Actions", "code": 37, From c4632a6363b7174f0fdd6219cf97309b4c35aac3 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Tue, 3 Dec 2024 10:38:17 -0500 Subject: [PATCH 130/219] Some code updates on composition logic after #36493 (#36681) * Remove some stutterning from endpoint composition (pattern repeated) * Remove some explitic bits, add comments about what endpoint composition patterns are * Restyle * Restyled by clang-format * Fix typo --------- Co-authored-by: Restyled.io --- src/app/clusters/descriptor/descriptor.cpp | 5 ++-- .../CodegenDataModelProvider.cpp | 4 +-- .../tests/TestCodegenModelViaMocks.cpp | 28 +++++++++---------- src/app/data-model-provider/MetadataTypes.h | 19 +++++++++---- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/app/clusters/descriptor/descriptor.cpp b/src/app/clusters/descriptor/descriptor.cpp index 409240e66a..7d8854bca1 100644 --- a/src/app/clusters/descriptor/descriptor.cpp +++ b/src/app/clusters/descriptor/descriptor.cpp @@ -105,8 +105,7 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu return CHIP_NO_ERROR; }); } - else if (endpointInfo.has_value() && - endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamilyPattern) + else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamily) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); @@ -134,7 +133,7 @@ CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, Attribu return CHIP_NO_ERROR; }); } - else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTreePattern) + else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTree) { err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR { auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint(); diff --git a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp index 4eae3de1e2..f4e1190d61 100644 --- a/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp +++ b/src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp @@ -321,11 +321,11 @@ std::optional GetEndpointInfoAtIndex(uint16_t endpointI EndpointId parent = emberAfParentEndpointFromIndex(endpointIndex); if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kFullFamily) { - return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kFullFamilyPattern); + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kFullFamily); } if (GetCompositionForEndpointIndex(endpointIndex) == EndpointComposition::kTree) { - return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kTreePattern); + return DataModel::EndpointInfo(parent, DataModel::EndpointCompositionPattern::kTree); } return std::nullopt; } diff --git a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp index 50d8ec67df..5f47f1abda 100644 --- a/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp +++ b/src/app/codegen-data-model-provider/tests/TestCodegenModelViaMocks.cpp @@ -898,15 +898,15 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) EndpointEntry ep = model.FirstEndpoint(); EXPECT_EQ(ep.id, kMockEndpoint1); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint3); EXPECT_EQ(ep.id, kInvalidEndpointId); @@ -914,27 +914,27 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint2); EXPECT_EQ(ep.id, kMockEndpoint3); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.NextEndpoint(kMockEndpoint1); EXPECT_EQ(ep.id, kMockEndpoint2); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTreePattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kTree); ep = model.NextEndpoint(kMockEndpoint3); EXPECT_EQ(ep.id, kInvalidEndpointId); ep = model.NextEndpoint(kMockEndpoint3); @@ -942,11 +942,11 @@ TEST(TestCodegenModelViaMocks, IterateOverEndpoints) ep = model.FirstEndpoint(); EXPECT_EQ(ep.id, kMockEndpoint1); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); ep = model.FirstEndpoint(); EXPECT_EQ(ep.id, kMockEndpoint1); EXPECT_EQ(ep.info.parentId, kInvalidEndpointId); - EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamilyPattern); + EXPECT_EQ(ep.info.compositionPattern, EndpointCompositionPattern::kFullFamily); // invalid endpoiunts ep = model.NextEndpoint(kInvalidEndpointId); @@ -964,17 +964,17 @@ TEST(TestCodegenModelViaMocks, GetEndpointInfo) ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) - EndpointCompositionPattern::kFullFamilyPattern); + EndpointCompositionPattern::kFullFamily); info = model.GetEndpointInfo(kMockEndpoint2); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) - EndpointCompositionPattern::kTreePattern); + EndpointCompositionPattern::kTree); info = model.GetEndpointInfo(kMockEndpoint3); ASSERT_TRUE(info.has_value()); EXPECT_EQ(info->parentId, kInvalidEndpointId); // NOLINT(bugprone-unchecked-optional-access) EXPECT_EQ(info->compositionPattern, // NOLINT(bugprone-unchecked-optional-access) - EndpointCompositionPattern::kFullFamilyPattern); + EndpointCompositionPattern::kFullFamily); // invalid endpoiunts info = model.GetEndpointInfo(kInvalidEndpointId); diff --git a/src/app/data-model-provider/MetadataTypes.h b/src/app/data-model-provider/MetadataTypes.h index ab9005412e..8f5a6cbf5a 100644 --- a/src/app/data-model-provider/MetadataTypes.h +++ b/src/app/data-model-provider/MetadataTypes.h @@ -33,10 +33,20 @@ namespace chip { namespace app { namespace DataModel { +/// Represents various endpoint composition patters as defined in the spec +/// as `9.2.1. Endpoint Composition patterns` enum class EndpointCompositionPattern : uint8_t { - kTreePattern = 0x1, - kFullFamilyPattern = 0x2, + // Tree pattern supports a general tree of endpoints. Commonly used for + // device types that support physical device composition (e.g. Refrigerator) + kTree = 0x1, + + // A full-family pattern is a list fo all descendant endpoints, with no + // imposed hierarchy. + // + // For example the Root Node and Aggregator device types use the full-familiy + // pattern, as defined in their device type specification + kFullFamily = 0x2, }; struct EndpointInfo @@ -46,9 +56,8 @@ struct EndpointInfo EndpointId parentId; EndpointCompositionPattern compositionPattern; - explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamilyPattern) - {} - explicit EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {} + explicit EndpointInfo(EndpointId parent) : parentId(parent), compositionPattern(EndpointCompositionPattern::kFullFamily) {} + EndpointInfo(EndpointId parent, EndpointCompositionPattern pattern) : parentId(parent), compositionPattern(pattern) {} }; struct EndpointEntry From 9a1d48c3e0471b84297ca6f83a15cf07d3863a0a Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Tue, 3 Dec 2024 18:38:01 +0100 Subject: [PATCH 131/219] [Fabric-Sync] Fix deadlock when removing device (#36706) * [Fabric-Sync] Fix deadlock when removing device * Add assertChipStackLockedByCurrentThread just in case --- .../fabric-sync/bridge/src/BridgedDeviceManager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp index 0ead453572..5057f5f68f 100644 --- a/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp +++ b/examples/fabric-sync/bridge/src/BridgedDeviceManager.cpp @@ -245,12 +245,13 @@ std::optional BridgedDeviceManager::AddDeviceEndpoint(std::unique_ptr< int BridgedDeviceManager::RemoveDeviceEndpoint(BridgedDevice * dev) { + assertChipStackLockedByCurrentThread(); + uint8_t index = 0; while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT) { if (mDevices[index].get() == dev) { - DeviceLayer::StackLock lock; // Silence complaints about unused ep when progress logging // disabled. [[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index); @@ -266,6 +267,8 @@ int BridgedDeviceManager::RemoveDeviceEndpoint(BridgedDevice * dev) BridgedDevice * BridgedDeviceManager::GetDevice(chip::EndpointId endpointId) const { + assertChipStackLockedByCurrentThread(); + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetEndpointId() == endpointId) @@ -304,6 +307,8 @@ std::string BridgedDeviceManager::GenerateUniqueId() BridgedDevice * BridgedDeviceManager::GetDeviceByUniqueId(const std::string & id) { + assertChipStackLockedByCurrentThread(); + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetBridgedAttributes().uniqueId == id) @@ -316,6 +321,8 @@ BridgedDevice * BridgedDeviceManager::GetDeviceByUniqueId(const std::string & id BridgedDevice * BridgedDeviceManager::GetDeviceByScopedNodeId(chip::ScopedNodeId scopedNodeId) const { + assertChipStackLockedByCurrentThread(); + for (uint8_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetScopedNodeId() == scopedNodeId) @@ -328,11 +335,12 @@ BridgedDevice * BridgedDeviceManager::GetDeviceByScopedNodeId(chip::ScopedNodeId std::optional BridgedDeviceManager::RemoveDeviceByScopedNodeId(chip::ScopedNodeId scopedNodeId) { + assertChipStackLockedByCurrentThread(); + for (uint16_t index = 0; index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; ++index) { if (mDevices[index] && mDevices[index]->GetScopedNodeId() == scopedNodeId) { - DeviceLayer::StackLock lock; EndpointId ep = emberAfClearDynamicEndpoint(index); mDevices[index] = nullptr; ChipLogProgress(NotSpecified, "Removed device with Id=[%d:0x" ChipLogFormatX64 "] from dynamic endpoint %d (index=%d)", From 9e85e85d09184b5813d5314e25e5435460d22c3a Mon Sep 17 00:00:00 2001 From: arun-silabs <141724790+arun-silabs@users.noreply.github.com> Date: Tue, 3 Dec 2024 23:50:02 +0530 Subject: [PATCH 132/219] FanControl: modify percentSetting/percentSpeedSetting return value in case NULL is written (match spec) (#36242) * Modified return value as per spec * Modified return value for speedSetting attribute * Updated test suite with return value. --- src/app/clusters/fan-control-server/fan-control-server.cpp | 4 ++-- src/app/tests/suites/TestFanControl.yaml | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/clusters/fan-control-server/fan-control-server.cpp b/src/app/clusters/fan-control-server/fan-control-server.cpp index 2c30c9c6cd..9767dc9246 100644 --- a/src/app/clusters/fan-control-server/fan-control-server.cpp +++ b/src/app/clusters/fan-control-server/fan-control-server.cpp @@ -212,7 +212,7 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute } else { - res = Status::WriteIgnored; + res = Status::InvalidInState; } } else @@ -252,7 +252,7 @@ MatterFanControlClusterServerPreAttributeChangedCallback(const ConcreteAttribute } else { - res = Status::WriteIgnored; + res = Status::InvalidInState; } } else diff --git a/src/app/tests/suites/TestFanControl.yaml b/src/app/tests/suites/TestFanControl.yaml index 92fca4f2a6..663bdf9e64 100644 --- a/src/app/tests/suites/TestFanControl.yaml +++ b/src/app/tests/suites/TestFanControl.yaml @@ -69,6 +69,8 @@ tests: attribute: "PercentSetting" arguments: value: null + response: + error: INVALID_IN_STATE - label: "Read back percent setting" command: "readAttribute" @@ -105,6 +107,8 @@ tests: attribute: "SpeedSetting" arguments: value: null + response: + error: INVALID_IN_STATE - label: "Read back speed setting" command: "readAttribute" From 8cd305004bc78114b3ef21a7b496ae6bb47b6d46 Mon Sep 17 00:00:00 2001 From: BoB13-Matter Date: Wed, 4 Dec 2024 06:43:49 +0900 Subject: [PATCH 133/219] Fix small typo in DataModelLogger-src.zapt (#36702) * Fix small typo in DataModelLogger-src.zapt * Update DataModelLogger.cpp --- examples/chip-tool/templates/logging/DataModelLogger-src.zapt | 2 +- .../chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/chip-tool/templates/logging/DataModelLogger-src.zapt b/examples/chip-tool/templates/logging/DataModelLogger-src.zapt index cbce6c27ab..d22e1afb07 100644 --- a/examples/chip-tool/templates/logging/DataModelLogger-src.zapt +++ b/examples/chip-tool/templates/logging/DataModelLogger-src.zapt @@ -100,7 +100,7 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP default: break; } - ChipLogProgress(chipTool, " Don't know how to log atribute value"); + ChipLogProgress(chipTool, " Don't know how to log attribute value"); return CHIP_NO_ERROR; } diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index 1ea513ea1d..9e44b001a1 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -19484,7 +19484,7 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP default: break; } - ChipLogProgress(chipTool, " Don't know how to log atribute value"); + ChipLogProgress(chipTool, " Don't know how to log attribute value"); return CHIP_NO_ERROR; } From 4cf28abd3a1ed2f6f754c66990ef932432fa1f19 Mon Sep 17 00:00:00 2001 From: Kiel Oleson Date: Tue, 3 Dec 2024 14:55:02 -0800 Subject: [PATCH 134/219] [Darwin] Framework diagnostics at startup (#36696) * add script to make git commit SHA of build available to framework via derived header * trigger diagnostic log at framework init * enumerate derived output file --- src/darwin/Framework/CHIP/MTRFramework.mm | 3 ++ .../Framework/CHIP/MTRFrameworkDiagnostics.h | 17 +++++++++++ .../Framework/CHIP/MTRFrameworkDiagnostics.mm | 24 ++++++++++++++++ .../Matter.xcodeproj/project.pbxproj | 28 +++++++++++++++++++ 4 files changed, 72 insertions(+) create mode 100644 src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h create mode 100644 src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm diff --git a/src/darwin/Framework/CHIP/MTRFramework.mm b/src/darwin/Framework/CHIP/MTRFramework.mm index e6a0e67295..49c9b7ee02 100644 --- a/src/darwin/Framework/CHIP/MTRFramework.mm +++ b/src/darwin/Framework/CHIP/MTRFramework.mm @@ -15,6 +15,7 @@ */ #import "MTRFramework.h" +#import "MTRFrameworkDiagnostics.h" #include #include @@ -34,5 +35,7 @@ void MTRFrameworkInit() // Suppress CHIP logging until we actually need it for redirection // (see MTRSetLogCallback()). Logging to os_log is always enabled. chip::Logging::SetLogFilter(chip::Logging::kLogCategory_None); + + MTRFrameworkInitDiagnosticLog(); }); } diff --git a/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h new file mode 100644 index 0000000000..57a90e3f95 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2024 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. + */ + +void MTRFrameworkInitDiagnosticLog(); diff --git a/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm new file mode 100644 index 0000000000..0cf93dc5b4 --- /dev/null +++ b/src/darwin/Framework/CHIP/MTRFrameworkDiagnostics.mm @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024 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. + */ + +#include "git_commit_sha.h" + +#import "MTRLogging_Internal.h" + +void MTRFrameworkInitDiagnosticLog() +{ + MTR_LOG("Matter Framework Init (git: %s)", GIT_COMMIT_SHA); +} diff --git a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj index 13f0eb8e20..8510fc3456 100644 --- a/src/darwin/Framework/Matter.xcodeproj/project.pbxproj +++ b/src/darwin/Framework/Matter.xcodeproj/project.pbxproj @@ -331,6 +331,8 @@ 99C65E10267282F1003402F6 /* MTRControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 99C65E0F267282F1003402F6 /* MTRControllerTests.m */; }; 99D466E12798936D0089A18F /* MTRCommissioningParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 99D466E02798936D0089A18F /* MTRCommissioningParameters.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9B0484F52C701154006C2D5F /* MTRDeviceController_Concrete.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B0484F42C701154006C2D5F /* MTRDeviceController_Concrete.h */; }; + 9B1728F02CFE573C00825030 /* MTRFrameworkDiagnostics.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B1728EF2CFE573600825030 /* MTRFrameworkDiagnostics.h */; }; + 9B1728F22CFE574600825030 /* MTRFrameworkDiagnostics.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B1728F12CFE574000825030 /* MTRFrameworkDiagnostics.mm */; }; 9B231B042C62EF650030EB37 /* (null) in Headers */ = {isa = PBXBuildFile; }; 9B231B052C62EF650030EB37 /* MTRDeviceController_Concrete.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */; }; 9B5CCB592C6E6FD3009DD99B /* MTRDeviceController_XPC_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B5CCB582C6E6FD3009DD99B /* MTRDeviceController_XPC_Internal.h */; }; @@ -811,6 +813,8 @@ 99C65E0F267282F1003402F6 /* MTRControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MTRControllerTests.m; sourceTree = ""; }; 99D466E02798936D0089A18F /* MTRCommissioningParameters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRCommissioningParameters.h; sourceTree = ""; }; 9B0484F42C701154006C2D5F /* MTRDeviceController_Concrete.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController_Concrete.h; sourceTree = ""; }; + 9B1728EF2CFE573600825030 /* MTRFrameworkDiagnostics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRFrameworkDiagnostics.h; sourceTree = ""; }; + 9B1728F12CFE574000825030 /* MTRFrameworkDiagnostics.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRFrameworkDiagnostics.mm; sourceTree = ""; }; 9B231B032C62EF650030EB37 /* MTRDeviceController_Concrete.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MTRDeviceController_Concrete.mm; sourceTree = ""; }; 9B5CCB582C6E6FD3009DD99B /* MTRDeviceController_XPC_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDeviceController_XPC_Internal.h; sourceTree = ""; }; 9B5CCB5A2C6EC890009DD99B /* MTRDevice_XPC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MTRDevice_XPC.h; sourceTree = ""; }; @@ -1514,6 +1518,8 @@ 754F3DF327FBB94B00E60580 /* MTREventTLVValueDecoder_Internal.h */, 515C1C6E284F9FFB00A48F0C /* MTRFramework.h */, 515C1C6D284F9FFB00A48F0C /* MTRFramework.mm */, + 9B1728EF2CFE573600825030 /* MTRFrameworkDiagnostics.h */, + 9B1728F12CFE574000825030 /* MTRFrameworkDiagnostics.mm */, 998F286C26D55E10001846C6 /* MTRKeypair.h */, 3DECCB6F2934AC1C00585AEC /* MTRLogging.h */, 991DC08A247704DC00C13860 /* MTRLogging_Internal.h */, @@ -1844,6 +1850,7 @@ 5178E6822AE098520069DF72 /* MTRCommissionableBrowserResult_Internal.h in Headers */, 516415FD2B6ACA8300D5CE11 /* MTRServerAccessControl.h in Headers */, 3CF134AB289D8DF70017A19E /* MTRDeviceAttestationInfo.h in Headers */, + 9B1728F02CFE573C00825030 /* MTRFrameworkDiagnostics.h in Headers */, B2E0D7B2245B0B5C003C5B48 /* MTRManualSetupPayloadParser.h in Headers */, 5109E9C02CCAD64F0006884B /* MTRDeviceDataValidation.h in Headers */, 3CF134A7289D8ADA0017A19E /* MTRCSRInfo.h in Headers */, @@ -1946,6 +1953,7 @@ isa = PBXNativeTarget; buildConfigurationList = B20252A12459E34F00F97062 /* Build configuration list for PBXNativeTarget "Matter" */; buildPhases = ( + 9B7838562CFE3AE600FB04C4 /* Acquire git revision info */, 0C40A67D246C9AC700885C81 /* Run GN Build (chip_xcode_build_connector) */, B20252882459E34F00F97062 /* Headers */, B20252892459E34F00F97062 /* Sources */, @@ -2059,6 +2067,25 @@ shellPath = /bin/sh; shellScript = "./chip_xcode_build_connector.sh\n"; }; + 9B7838562CFE3AE600FB04C4 /* Acquire git revision info */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Acquire git revision info"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/git_commit_sha.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "GIT_COMMIT_SHA=$(git rev-parse --short HEAD)\n\n# Create a temporary header file to hold the commit SHA\ntmp_header_path=\"${DERIVED_FILES_DIR}/git_commit_sha.h\"\ncat << EOF > \"$tmp_header_path\"\n#ifndef GIT_COMMIT_SHA_H\n#define GIT_COMMIT_SHA_H\n\n#define GIT_COMMIT_SHA \"${GIT_COMMIT_SHA}\"\n\n#endif /* GIT_COMMIT_SHA_H */\nEOF\n\necho \"git sha available in ${DERIVED_FILES_DIR}/git_commit_sha.h\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -2198,6 +2225,7 @@ AF5F90FF2878D351005503FA /* MTROTAProviderDelegateBridge.mm in Sources */, 516415FF2B6B132200D5CE11 /* DataModelHandler.cpp in Sources */, 75139A6F2B7FE5E900E3A919 /* MTRDeviceControllerLocalTestStorage.mm in Sources */, + 9B1728F22CFE574600825030 /* MTRFrameworkDiagnostics.mm in Sources */, 51E95DFC2A78443C00A434F0 /* MTRSessionResumptionStorageBridge.mm in Sources */, 7534F12828BFF20300390851 /* MTRDeviceAttestationDelegate.mm in Sources */, B4C8E6B72B3453AD00FCD54D /* MTRDiagnosticLogsDownloader.mm in Sources */, From 0495a4eab31e12bba0f099fed15a83dc84ebb953 Mon Sep 17 00:00:00 2001 From: C Freeman Date: Tue, 3 Dec 2024 18:24:49 -0500 Subject: [PATCH 135/219] Python testing: Update commissioning window API (#36669) * Python testing: Update commissioning window API - add some defaults to make this easier to use - change the name to match the other methods in the class * Fix API for new test --- src/python_testing/TC_ACE_1_5.py | 2 +- src/python_testing/TC_BRBINFO_4_1.py | 2 +- src/python_testing/TC_CADMIN_1_19.py | 4 ++-- src/python_testing/TC_CCTRL_2_2.py | 2 +- src/python_testing/TC_OPCREDS_3_4.py | 2 +- .../chip/testing/matter_testing.py | 10 +++++----- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/python_testing/TC_ACE_1_5.py b/src/python_testing/TC_ACE_1_5.py index 15c7380d23..9bcd92f81e 100644 --- a/src/python_testing/TC_ACE_1_5.py +++ b/src/python_testing/TC_ACE_1_5.py @@ -71,7 +71,7 @@ async def test_TC_ACE_1_5(self): self.th2 = new_fabric_admin.NewController(nodeId=TH2_nodeid, paaTrustStorePath=str(self.matter_test_config.paa_trust_store_path)) - params = await self.openCommissioningWindow(self.th1, self.dut_node_id) + params = await self.open_commissioning_window(self.th1, self.dut_node_id) self.print_step(2, "TH1 opens the commissioning window on the DUT") await self.th2.CommissionOnNetwork( diff --git a/src/python_testing/TC_BRBINFO_4_1.py b/src/python_testing/TC_BRBINFO_4_1.py index f5eeec3344..8c929d39b9 100644 --- a/src/python_testing/TC_BRBINFO_4_1.py +++ b/src/python_testing/TC_BRBINFO_4_1.py @@ -189,7 +189,7 @@ async def setup_class(self): filter=self.th_icd_server_discriminator) logging.info("Commissioning of ICD to fabric two (DUT)") - params = await self.openCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.icd_nodeid) + params = await self.open_commissioning_window(dev_ctrl=self.default_controller, node_id=self.icd_nodeid) if not self.is_pics_sdk_ci_only: self._ask_for_vendor_commissioning_ux_operation( diff --git a/src/python_testing/TC_CADMIN_1_19.py b/src/python_testing/TC_CADMIN_1_19.py index 5ec3da867d..90a3d676b7 100644 --- a/src/python_testing/TC_CADMIN_1_19.py +++ b/src/python_testing/TC_CADMIN_1_19.py @@ -111,7 +111,7 @@ async def test_TC_CADMIN_1_19(self): self.current_step_index = 4 self.step("4a") - params = await self.openCommissioningWindow(dev_ctrl=self.th1, timeout=self.max_window_duration, node_id=self.dut_node_id) + params = await self.open_commissioning_window(dev_ctrl=self.th1, timeout=self.max_window_duration, node_id=self.dut_node_id) self.step("4b") fids_ca_dir[fid] = self.certificate_authority_manager.NewCertificateAuthority() @@ -128,7 +128,7 @@ async def test_TC_CADMIN_1_19(self): asserts.assert_equal(current_fabrics, max_fabrics, "Expected number of fabrics not correct") self.step(6) - params = await self.openCommissioningWindow(dev_ctrl=self.th1, node_id=self.dut_node_id) + params = await self.open_commissioning_window(dev_ctrl=self.th1, node_id=self.dut_node_id) self.step(7) # TH creates a controller on a new fabric and attempts to commission DUT_CE using that controller diff --git a/src/python_testing/TC_CCTRL_2_2.py b/src/python_testing/TC_CCTRL_2_2.py index 1bc403a7e4..3f60fd9e38 100644 --- a/src/python_testing/TC_CCTRL_2_2.py +++ b/src/python_testing/TC_CCTRL_2_2.py @@ -170,7 +170,7 @@ async def test_TC_CCTRL_2_2(self): asserts.assert_equal(e.status, Status.Failure, "Incorrect error returned") self.step(6) - params = await self.openCommissioningWindow(dev_ctrl=self.default_controller, node_id=self.dut_node_id) + params = await self.open_commissioning_window(dev_ctrl=self.default_controller, node_id=self.dut_node_id) self.step(7) pase_nodeid = self.dut_node_id + 1 await self.default_controller.FindOrEstablishPASESession(setupCode=params.commissioningParameters.setupQRCode, nodeid=pase_nodeid) diff --git a/src/python_testing/TC_OPCREDS_3_4.py b/src/python_testing/TC_OPCREDS_3_4.py index e2657ba160..c13f1ced75 100644 --- a/src/python_testing/TC_OPCREDS_3_4.py +++ b/src/python_testing/TC_OPCREDS_3_4.py @@ -273,7 +273,7 @@ async def test_TC_OPCREDS_3_4(self): "Failure status returned from arm failsafe") self.step(22) - resp = await self.openCommissioningWindow(self.default_controller, self.dut_node_id) + resp = await self.open_commissioning_window() self.step(23) await self.default_controller.FindOrEstablishPASESession(setupCode=resp.commissioningParameters.setupQRCode, nodeid=self.dut_node_id) diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index a88b57e602..e5bdf2b3be 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -1141,8 +1141,12 @@ def check_pics(self, pics_key: str) -> bool: def is_pics_sdk_ci_only(self) -> bool: return self.check_pics('PICS_SDK_CI_ONLY') - async def openCommissioningWindow(self, dev_ctrl: ChipDeviceCtrl, node_id: int, timeout: int = 900) -> CustomCommissioningParameters: + async def open_commissioning_window(self, dev_ctrl: Optional[ChipDeviceCtrl] = None, node_id: Optional[int] = None, timeout: int = 900) -> CustomCommissioningParameters: rnd_discriminator = random.randint(0, 4095) + if dev_ctrl is None: + dev_ctrl = self.default_controller + if node_id is None: + node_id = self.dut_node_id try: commissioning_params = await dev_ctrl.OpenCommissioningWindow(nodeid=node_id, timeout=timeout, iteration=1000, discriminator=rnd_discriminator, option=1) @@ -1166,7 +1170,6 @@ async def read_single_attribute_check_success( if node_id is None: node_id = self.dut_node_id if endpoint is None: - #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint endpoint = self.get_endpoint() result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabric_filtered) @@ -1199,7 +1202,6 @@ async def read_single_attribute_expect_error( if node_id is None: node_id = self.dut_node_id if endpoint is None: - #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint endpoint = self.get_endpoint() result = await dev_ctrl.ReadAttribute(node_id, [(endpoint, attribute)], fabricFiltered=fabric_filtered) @@ -1248,7 +1250,6 @@ async def send_single_cmd( if node_id is None: node_id = self.dut_node_id if endpoint is None: - #endpoint = 0 if self.matter_test_config.endpoint is None else self.matter_test_config.endpoint endpoint = self.get_endpoint() result = await dev_ctrl.SendCommand(nodeid=node_id, endpoint=endpoint, payload=cmd, timedRequestTimeoutMs=timedRequestTimeoutMs, @@ -1842,7 +1843,6 @@ def convert_args_to_matter_config(args: argparse.Namespace) -> MatterTestConfig: config.pics = {} if args.PICS is None else read_pics_from_file(args.PICS) config.tests = [] if args.tests is None else args.tests config.timeout = args.timeout # This can be none, we pull the default from the test if it's unspecified - #config.endpoint = args.endpoint config.endpoint = args.endpoint # This can be None, the get_endpoint function allows the tests to supply a default config.app_pid = 0 if args.app_pid is None else args.app_pid From e0fc29a8f10a37a6dde44a5c6ba1686e1b55274d Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Tue, 3 Dec 2024 15:59:27 -0800 Subject: [PATCH 136/219] [Fabric-Sync]: Convert ember-driven functions to interface functions (#36659) * [Fabric-Sync]: Convert ember-driven functions to interface functions * Address review comments --- .../linux/CommissionerControlDelegate.cpp | 6 +- .../include/CommissionerControlDelegate.h | 6 + .../include/CommissionerControlDelegate.h | 7 +- .../src/CommissionerControlDelegate.cpp | 6 +- .../commissioner-control-server.cpp | 169 +++++++++--------- .../commissioner-control-server.h | 45 ++++- src/app/common/templates/config-data.yaml | 1 + .../app-common/zap-generated/callback.h | 12 -- 8 files changed, 143 insertions(+), 109 deletions(-) diff --git a/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp b/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp index aa12a4274c..ca963a178d 100644 --- a/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp +++ b/examples/fabric-bridge-app/linux/CommissionerControlDelegate.cpp @@ -116,7 +116,7 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const mLabel.ClearValue(); } - CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); + CHIP_ERROR err = mCommissionerControlServer.GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); if (err == CHIP_NO_ERROR) { @@ -228,7 +228,7 @@ CHIP_ERROR CommissionerControlInit() return CHIP_ERROR_NO_MEMORY; } - err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate); + err = sCommissionerControlDelegate->GetCommissionerControlServer().Init(); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate."); @@ -242,7 +242,7 @@ CHIP_ERROR CommissionerControlInit() supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1); Protocols::InteractionModel::Status status = - Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue( + sCommissionerControlDelegate->GetCommissionerControlServer().SetSupportedDeviceCategoriesValue( Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories); if (status != Protocols::InteractionModel::Status::Success) diff --git a/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h b/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h index 2f9e15f508..a39f490668 100644 --- a/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h +++ b/examples/fabric-bridge-app/linux/include/CommissionerControlDelegate.h @@ -31,6 +31,8 @@ inline constexpr EndpointId kAggregatorEndpointId = 1; class CommissionerControlDelegate : public Delegate { public: + CommissionerControlDelegate() : mCommissionerControlServer(this, kAggregatorEndpointId, CommissionerControl::Id) {} + CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; // TODO(#35627) clientNodeId should move towards ScopedNodeId. CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) override; @@ -39,6 +41,8 @@ class CommissionerControlDelegate : public Delegate ~CommissionerControlDelegate() = default; + CommissionerControlServer & GetCommissionerControlServer() { return mCommissionerControlServer; } + private: enum class Step : uint8_t { @@ -82,6 +86,8 @@ class CommissionerControlDelegate : public Delegate ByteSpan mPBKDFSalt; Crypto::Spake2pVerifierSerialized mPAKEPasscodeVerifierBuffer; ByteSpan mPAKEPasscodeVerifier; + + CommissionerControlServer mCommissionerControlServer; }; } // namespace CommissionerControl diff --git a/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h b/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h index 45a927307b..9dc4fac374 100644 --- a/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h +++ b/examples/fabric-sync/bridge/include/CommissionerControlDelegate.h @@ -32,7 +32,9 @@ inline constexpr EndpointId kAggregatorEndpointId = 1; class CommissionerControlDelegate : public Delegate { public: - CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) : mFabricAdmin(fabricAdmin) {} + CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) : + mFabricAdmin(fabricAdmin), mCommissionerControlServer(this, kAggregatorEndpointId, CommissionerControl::Id) + {} CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override; // TODO(#35627) clientNodeId should move towards ScopedNodeId. @@ -42,6 +44,8 @@ class CommissionerControlDelegate : public Delegate ~CommissionerControlDelegate() = default; + CommissionerControlServer & GetCommissionerControlServer() { return mCommissionerControlServer; } + private: enum class Step : uint8_t { @@ -87,6 +91,7 @@ class CommissionerControlDelegate : public Delegate ByteSpan mPAKEPasscodeVerifier; bridge::FabricAdminDelegate * mFabricAdmin; + CommissionerControlServer mCommissionerControlServer; }; } // namespace CommissionerControl diff --git a/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp b/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp index 12851177bc..f3b0a398d1 100644 --- a/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp +++ b/examples/fabric-sync/bridge/src/CommissionerControlDelegate.cpp @@ -114,7 +114,7 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const mLabel.ClearValue(); } - CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); + CHIP_ERROR err = mCommissionerControlServer.GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result); if (err == CHIP_NO_ERROR) { @@ -227,7 +227,7 @@ CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin) return CHIP_ERROR_NO_MEMORY; } - err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate); + err = sCommissionerControlDelegate->GetCommissionerControlServer().Init(); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate."); @@ -241,7 +241,7 @@ CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin) supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1); Protocols::InteractionModel::Status status = - Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue( + sCommissionerControlDelegate->GetCommissionerControlServer().SetSupportedDeviceCategoriesValue( Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories); if (status != Protocols::InteractionModel::Status::Success) diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp index ea0c9b1203..9a0e91a2d0 100644 --- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp @@ -22,11 +22,11 @@ #include #include #include -#include -#include #include +#include #include #include +#include #include #include @@ -38,9 +38,9 @@ using chip::Protocols::InteractionModel::Status; namespace { -NodeId GetNodeId(const CommandHandler * commandObj) +NodeId GetNodeId(const CommandHandler & commandHandler) { - auto descriptor = commandObj->GetSubjectDescriptor(); + auto descriptor = commandHandler.GetSubjectDescriptor(); if (descriptor.authMode != Access::AuthMode::kCase) { @@ -49,7 +49,7 @@ NodeId GetNodeId(const CommandHandler * commandObj) return descriptor.subject; } -void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path, +void AddReverseOpenCommissioningWindowResponse(CommandHandler & commandHandler, const ConcreteCommandPath & path, const Clusters::CommissionerControl::CommissioningWindowParams & params) { Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Type response; @@ -59,30 +59,7 @@ void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, cons response.PAKEPasscodeVerifier = params.PAKEPasscodeVerifier; response.salt = params.salt; - commandObj->AddResponse(path, response); -} - -void RunDeferredCommissionNode(intptr_t commandArg) -{ - auto * params = reinterpret_cast(commandArg); - - Clusters::CommissionerControl::Delegate * delegate = - Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); - - if (delegate != nullptr) - { - CHIP_ERROR err = delegate->HandleCommissionNode(*params); - if (err != CHIP_NO_ERROR) - { - ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); - } - } - else - { - ChipLogError(Zcl, "No delegate available for HandleCommissionNode"); - } - - delete params; + commandHandler.AddResponse(path, response); } } // namespace @@ -92,16 +69,20 @@ namespace app { namespace Clusters { namespace CommissionerControl { -CommissionerControlServer CommissionerControlServer::sInstance; +CommissionerControlServer::CommissionerControlServer(Delegate * delegate, EndpointId endpointId, ClusterId clusterId) : + CommandHandlerInterface(MakeOptional(endpointId), clusterId) +{ + mDelegate = delegate; +} -CommissionerControlServer & CommissionerControlServer::Instance() +CommissionerControlServer::~CommissionerControlServer() { - return sInstance; + CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); } -CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate) +CHIP_ERROR CommissionerControlServer::Init() { - mDelegate = &delegate; + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); return CHIP_NO_ERROR; } @@ -146,38 +127,53 @@ CommissionerControlServer::GenerateCommissioningRequestResultEvent(EndpointId en return error; } -} // namespace CommissionerControl -} // namespace Clusters -} // namespace app -} // namespace chip +void CommissionerControlServer::InvokeCommand(HandlerContext & handlerContext) +{ + ChipLogDetail(Zcl, "CommissionerControl: InvokeCommand"); + switch (handlerContext.mRequestPath.mCommandId) + { + case Commands::RequestCommissioningApproval::Id: + ChipLogDetail(Zcl, "CommissionerControl: Entering RequestCommissioningApproval"); -bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( - app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData) + CommandHandlerInterface::HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & req) { HandleRequestCommissioningApproval(ctx, req); }); + break; + + case Commands::CommissionNode::Id: + ChipLogDetail(Zcl, "CommissionerControl: Entering CommissionNode"); + + CommandHandlerInterface::HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & req) { HandleCommissionNode(ctx, req); }); + break; + } +} + +void CommissionerControlServer::HandleRequestCommissioningApproval( + HandlerContext & ctx, const Commands::RequestCommissioningApproval::DecodableType & req) { CHIP_ERROR err = CHIP_NO_ERROR; Status status = Status::Success; ChipLogProgress(Zcl, "Received command to request commissioning approval"); - auto sourceNodeId = GetNodeId(commandObj); + auto sourceNodeId = GetNodeId(ctx.mCommandHandler); // Check if the command is executed via a CASE session if (sourceNodeId == kUndefinedNodeId) { ChipLogError(Zcl, "Commissioning approval request not executed via CASE session, failing with UNSUPPORTED_ACCESS"); - commandObj->AddStatus(commandPath, Status::UnsupportedAccess); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess); + return; } - auto fabricIndex = commandObj->GetAccessingFabricIndex(); - auto requestId = commandData.requestID; - auto vendorId = commandData.vendorID; - auto productId = commandData.productID; + auto fabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex(); + auto requestId = req.requestID; + auto vendorId = req.vendorID; + auto productId = req.productID; - // The label assigned from commandData need to be stored in CommissionerControl::Delegate which ensure that the backing buffer + // The label assigned from req need to be stored in CommissionerControl::Delegate which ensure that the backing buffer // of it has a valid lifespan during fabric sync setup process. - auto & label = commandData.label; + auto & label = req.label; // Create a CommissioningApprovalRequest struct and populate it with the command data Clusters::CommissionerControl::CommissioningApprovalRequest request = { .requestId = requestId, @@ -187,86 +183,93 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( .fabricIndex = fabricIndex, .label = label }; - Clusters::CommissionerControl::Delegate * delegate = - Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); - - VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // Handle commissioning approval request - err = delegate->HandleCommissioningApprovalRequest(request); + err = mDelegate->HandleCommissioningApprovalRequest(request); exit: if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT, - err.Format()); + ChipLogError(Zcl, "HandleRequestCommissioningApproval error: %" CHIP_ERROR_FORMAT, err.Format()); status = StatusIB(err).mStatus; } - commandObj->AddStatus(commandPath, status); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); } -bool emberAfCommissionerControlClusterCommissionNodeCallback( - app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData) +void CommissionerControlServer::HandleCommissionNode(HandlerContext & ctx, const Commands::CommissionNode::DecodableType & req) { CHIP_ERROR err = CHIP_NO_ERROR; ChipLogProgress(Zcl, "Received command to commission node"); - auto sourceNodeId = GetNodeId(commandObj); + auto sourceNodeId = GetNodeId(ctx.mCommandHandler); // Constraint on responseTimeoutSeconds is [30; 120] seconds - if ((commandData.responseTimeoutSeconds < 30) || (commandData.responseTimeoutSeconds > 120)) + if ((req.responseTimeoutSeconds < 30) || (req.responseTimeoutSeconds > 120)) { ChipLogError(Zcl, "Invalid responseTimeoutSeconds for CommissionNode."); - commandObj->AddStatus(commandPath, Status::ConstraintError); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); + return; } // Check if the command is executed via a CASE session if (sourceNodeId == kUndefinedNodeId) { ChipLogError(Zcl, "Commission node request not executed via CASE session, failing with UNSUPPORTED_ACCESS"); - commandObj->AddStatus(commandPath, Status::UnsupportedAccess); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess); + return; } - auto requestId = commandData.requestID; - + auto requestId = req.requestID; + auto delegate = mDelegate; auto commissioningWindowParams = std::make_unique(); - Clusters::CommissionerControl::Delegate * delegate = - Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate(); - - VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE); // Validate the commission node command. - err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId); + err = mDelegate->ValidateCommissionNodeCommand(sourceNodeId, requestId); SuccessOrExit(err); // Populate the parameters for the commissioning window - err = delegate->GetCommissioningWindowParams(*commissioningWindowParams); + err = mDelegate->GetCommissioningWindowParams(*commissioningWindowParams); SuccessOrExit(err); // Add the response for the commissioning window. - AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, *commissioningWindowParams); + AddReverseOpenCommissioningWindowResponse(ctx.mCommandHandler, ctx.mRequestPath, *commissioningWindowParams); // Schedule the deferred reverse commission node task - DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, - reinterpret_cast(commissioningWindowParams.release())); + DeviceLayer::SystemLayer().ScheduleLambda([delegate, params = commissioningWindowParams.release()]() { + if (delegate != nullptr) + { + CHIP_ERROR error = delegate->HandleCommissionNode(*params); + if (error != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, error.Format()); + } + } + else + { + ChipLogError(Zcl, "No delegate available for HandleCommissionNode"); + } + + delete params; + }); exit: if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %" CHIP_ERROR_FORMAT, err.Format()); - commandObj->AddStatus(commandPath, StatusIB(err).mStatus); + ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format()); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus); } - - return true; } +} // namespace CommissionerControl +} // namespace Clusters +} // namespace app +} // namespace chip + void MatterCommissionerControlPluginServerInitCallback() { ChipLogProgress(Zcl, "Initializing Commissioner Control cluster."); diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h index 56f43620b5..2319a71cc9 100644 --- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h +++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h @@ -18,6 +18,7 @@ #pragma once #include +#include namespace chip { namespace app { @@ -100,14 +101,27 @@ class Delegate virtual ~Delegate() = default; }; -class CommissionerControlServer +class CommissionerControlServer : public CommandHandlerInterface { public: - static CommissionerControlServer & Instance(); + /** + * @brief Creates a Commissioner Control cluster instance. The Init() function needs to be called for this instance + * to be registered and called by the interaction model at the appropriate times. + * @param delegate A pointer to the delegate to be used by this server. + * Note: the caller must ensure that the delegate lives throughout the instance's lifetime. + * @param endpointId The endpoint on which this cluster exists. This must match the zap configuration. + * @param clusterId The ID of the Microwave Oven Control cluster to be instantiated. + */ + CommissionerControlServer(Delegate * delegate, EndpointId endpointId, ClusterId clusterId); - CHIP_ERROR Init(Delegate & delegate); + ~CommissionerControlServer() override; - Delegate * GetDelegate() { return mDelegate; } + /** + * @brief Initialise the Commissioner Control server instance. + * This function must be called after defining an CommissionerControlServer class object. + * @return Returns an error if the CommandHandler registration fails, else returns CHIP_NO_ERROR. + */ + CHIP_ERROR Init(); Protocols::InteractionModel::Status GetSupportedDeviceCategoriesValue(EndpointId endpoint, @@ -124,10 +138,27 @@ class CommissionerControlServer const Events::CommissioningRequestResult::Type & result); private: - CommissionerControlServer() = default; - ~CommissionerControlServer() = default; + /** + * @brief Inherited from CommandHandlerInterface + */ + void InvokeCommand(HandlerContext & ctx) override; - static CommissionerControlServer sInstance; + /** + * @brief Handle Command: SetCookingParameters. + * @param ctx Returns the Interaction Model status code which was user determined in the business logic. + * If the input value is invalid, returns the Interaction Model status code of INVALID_COMMAND. + * If the operational state is not in 'Stopped', returns the Interaction Model status code of INVALID_IN_STATE. + */ + void HandleRequestCommissioningApproval(HandlerContext & ctx, + const Commands::RequestCommissioningApproval::DecodableType & req); + + /** + * @brief Handle Command: AddMoreTime. + * @param ctx Returns the Interaction Model status code which was user determined in the business logic. + * If the cook time value is out of range, returns the Interaction Model status code of CONSTRAINT_ERROR. + * If the operational state is in 'Error', returns the Interaction Model status code of INVALID_IN_STATE. + */ + void HandleCommissionNode(HandlerContext & ctx, const Commands::CommissionNode::DecodableType & req); Delegate * mDelegate = nullptr; }; diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index f5259748d9..b014f103e9 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -37,6 +37,7 @@ CommandHandlerInterfaceOnlyClusters: - Sample MEI - Microwave Oven Control - Chime + - Commissioner Control - Energy EVSE - Energy EVSE Mode - Device Energy Management diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index 1c8cccc476..b594c4cce7 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -6906,18 +6906,6 @@ bool emberAfWebRTCTransportRequestorClusterICECandidateCallback( bool emberAfWebRTCTransportRequestorClusterEndCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::WebRTCTransportRequestor::Commands::End::DecodableType & commandData); -/** - * @brief Commissioner Control Cluster RequestCommissioningApproval Command callback (from client) - */ -bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData); -/** - * @brief Commissioner Control Cluster CommissionNode Command callback (from client) - */ -bool emberAfCommissionerControlClusterCommissionNodeCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData); /** * @brief Unit Testing Cluster Test Command callback (from client) */ From 9fe08439dcefb0fc189400b51034acec608140fa Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Wed, 4 Dec 2024 12:57:58 +0100 Subject: [PATCH 137/219] Support for generating QR-code and manual code in Python chip binding (#36692) * Support for generating QR-code and manual code in Python chip binding * Add SetupParameters wrapper to matter testing * Migrate to SetupParameters in tests * Restyled by autopep8 * Restyled by isort * Remove unused import --------- Co-authored-by: Restyled.io --- .../python/chip/setup_payload/Generator.cpp | 71 +++++++++++++++---- .../chip/setup_payload/setup_payload.py | 22 +++++- src/python_testing/TC_MCORE_FS_1_2.py | 24 ++----- src/python_testing/TC_MCORE_FS_1_5.py | 24 ++----- .../chip/testing/matter_testing.py | 21 ++++++ 5 files changed, 115 insertions(+), 47 deletions(-) diff --git a/src/controller/python/chip/setup_payload/Generator.cpp b/src/controller/python/chip/setup_payload/Generator.cpp index 4481a40446..442d009414 100644 --- a/src/controller/python/chip/setup_payload/Generator.cpp +++ b/src/controller/python/chip/setup_payload/Generator.cpp @@ -15,30 +15,30 @@ * limitations under the License. */ +#include +#include + #include +#include #include #include #include -#include -#include - using namespace chip; -extern "C" PyChipError pychip_SetupPayload_PrintOnboardingCodes(uint32_t passcode, uint16_t vendorId, uint16_t productId, - uint16_t discriminator, uint8_t customFlow, uint8_t capabilities, - uint8_t version) +namespace { + +CHIP_ERROR InitSetupPayload(SetupPayload & payload, uint32_t passcode, uint16_t vendorId, uint16_t productId, + uint16_t discriminator, uint8_t customFlow, uint8_t capabilities, uint8_t version) { - std::string QRCode; - std::string manualPairingCode; - SetupPayload payload; - RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kNone; payload.version = version; payload.setUpPINCode = passcode; payload.vendorID = vendorId; payload.productID = productId; payload.discriminator.SetLongValue(discriminator); + + RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kNone; payload.rendezvousInformation.SetValue(rendezvousFlags.SetRaw(capabilities)); switch (customFlow) @@ -54,16 +54,63 @@ extern "C" PyChipError pychip_SetupPayload_PrintOnboardingCodes(uint32_t passcod break; default: ChipLogError(SetupPayload, "Invalid Custom Flow"); - return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT); + return CHIP_ERROR_INVALID_ARGUMENT; } - CHIP_ERROR err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); + return CHIP_NO_ERROR; +} + +} // namespace + +extern "C" PyChipError pychip_SetupPayload_PrintOnboardingCodes(uint32_t passcode, uint16_t vendorId, uint16_t productId, + uint16_t discriminator, uint8_t customFlow, uint8_t capabilities, + uint8_t version) +{ + SetupPayload payload; + CHIP_ERROR err = InitSetupPayload(payload, passcode, vendorId, productId, discriminator, customFlow, capabilities, version); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + std::string manualPairingCode; + err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); ChipLogProgress(SetupPayload, "Manual pairing code: [%s]", manualPairingCode.c_str()); + std::string QRCode; err = QRCodeSetupPayloadGenerator(payload).payloadBase38Representation(QRCode); VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); ChipLogProgress(SetupPayload, "SetupQRCode: [%s]", QRCode.c_str()); return ToPyChipError(CHIP_NO_ERROR); } + +extern "C" PyChipError pychip_SetupPayload_GenerateQrCode(char * output, size_t size, uint32_t passcode, uint16_t vendorId, + uint16_t productId, uint16_t discriminator, uint8_t customFlow, + uint8_t capabilities, uint8_t version) +{ + SetupPayload payload; + CHIP_ERROR err = InitSetupPayload(payload, passcode, vendorId, productId, discriminator, customFlow, capabilities, version); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + std::string QRCode; + err = QRCodeSetupPayloadGenerator(payload).payloadBase38Representation(QRCode); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + Platform::CopyString(output, size, QRCode.c_str()); + return ToPyChipError(CHIP_NO_ERROR); +} + +extern "C" PyChipError pychip_SetupPayload_GenerateManualPairingCode(char * output, size_t size, uint32_t passcode, + uint16_t vendorId, uint16_t productId, uint16_t discriminator, + uint8_t customFlow, uint8_t capabilities, uint8_t version) +{ + SetupPayload payload; + CHIP_ERROR err = InitSetupPayload(payload, passcode, vendorId, productId, discriminator, customFlow, capabilities, version); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + std::string manualPairingCode; + err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); + VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); + + Platform::CopyString(output, size, manualPairingCode.c_str()); + return ToPyChipError(CHIP_NO_ERROR); +} diff --git a/src/controller/python/chip/setup_payload/setup_payload.py b/src/controller/python/chip/setup_payload/setup_payload.py index 702fb319b4..31a7030187 100644 --- a/src/controller/python/chip/setup_payload/setup_payload.py +++ b/src/controller/python/chip/setup_payload/setup_payload.py @@ -14,7 +14,7 @@ # limitations under the License. # -from ctypes import CFUNCTYPE, c_char_p, c_uint8, c_uint16, c_uint32 +from ctypes import CFUNCTYPE, c_char_p, c_uint8, c_uint16, c_uint32, c_uint64, create_string_buffer from typing import Optional from chip.native import GetLibraryHandle, NativeLibraryHandleMethodArguments, PyChipError @@ -43,6 +43,20 @@ def AddVendorAttribute(tag, value): self.vendor_attribute_visitor = SetupPayload.VendorAttributeVisitor( AddVendorAttribute) + def GenerateQrCode(self, passcode: int, vendorId: int = 0xFFF1, productId: int = 0x8001, discriminator: int = 3840, + customFlow: int = 0, capabilities: int = 4, version: int = 0) -> str: + buffer = create_string_buffer(256) + self.chipLib.pychip_SetupPayload_GenerateQrCode(buffer, 256, passcode, vendorId, productId, + discriminator, customFlow, capabilities, version).raise_on_error() + return buffer.value.decode() + + def GenerateManualPairingCode(self, passcode: int, vendorId: int = 0xFFF1, productId: int = 0x8001, discriminator: int = 3840, + customFlow: int = 0, capabilities: int = 4, version: int = 0) -> str: + buffer = create_string_buffer(256) + self.chipLib.pychip_SetupPayload_GenerateManualPairingCode(buffer, 256, passcode, vendorId, productId, + discriminator, customFlow, capabilities, version).raise_on_error() + return buffer.value.decode() + def ParseQrCode(self, qrCode: str): self.Clear() self.chipLib.pychip_SetupPayload_ParseQrCode(qrCode.upper().encode(), @@ -99,6 +113,12 @@ def __InitNativeFunctions(self, chipLib): if chipLib.pychip_SetupPayload_ParseQrCode.argtypes is not None: return setter = NativeLibraryHandleMethodArguments(chipLib) + setter.Set("pychip_SetupPayload_GenerateQrCode", + PyChipError, + [c_char_p, c_uint64, c_uint32, c_uint16, c_uint16, c_uint16, c_uint8, c_uint8, c_uint8]) + setter.Set("pychip_SetupPayload_GenerateManualPairingCode", + PyChipError, + [c_char_p, c_uint64, c_uint32, c_uint16, c_uint16, c_uint16, c_uint8, c_uint8, c_uint8]) setter.Set("pychip_SetupPayload_ParseQrCode", PyChipError, [c_char_p, SetupPayload.AttributeVisitor, SetupPayload.VendorAttributeVisitor]) diff --git a/src/python_testing/TC_MCORE_FS_1_2.py b/src/python_testing/TC_MCORE_FS_1_2.py index f806db4d09..97b5b87017 100644 --- a/src/python_testing/TC_MCORE_FS_1_2.py +++ b/src/python_testing/TC_MCORE_FS_1_2.py @@ -42,16 +42,17 @@ import logging import os import queue +import random import secrets import struct import tempfile import time -from dataclasses import dataclass import chip.clusters as Clusters from chip import ChipDeviceCtrl from chip.testing.apps import AppServerSubprocess -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from chip.testing.matter_testing import (MatterBaseTest, SetupParameters, TestStep, async_test_body, default_matter_test_main, + type_matches) from ecdsa.curves import NIST256p from mobly import asserts from TC_SC_3_6 import AttributeChangeAccumulator @@ -69,14 +70,6 @@ def _generate_verifier(passcode: int, salt: bytes, iterations: int) -> bytes: return w0.to_bytes(NIST256p.baselen, byteorder='big') + L.to_bytes('uncompressed') -@dataclass -class _SetupParameters: - setup_qr_code: str - manual_code: int - discriminator: int - passcode: int - - class TC_MCORE_FS_1_2(MatterBaseTest): @async_test_body async def setup_class(self): @@ -105,11 +98,8 @@ async def setup_class(self): self.dut_fsa_stdin = open(dut_fsa_stdin_pipe, "w") self.th_server_port = th_server_port - # These are default testing values. - self.th_server_setup_params = _SetupParameters( - setup_qr_code="MT:-24J0AFN00KA0648G00", - manual_code=34970112332, - discriminator=3840, + self.th_server_setup_params = SetupParameters( + discriminator=random.randint(0, 4095), passcode=20202021) # Start the TH_SERVER app. @@ -133,12 +123,12 @@ def teardown_class(self): self.storage.cleanup() super().teardown_class() - def _ask_for_vendor_commissioning_ux_operation(self, setup_params: _SetupParameters): + def _ask_for_vendor_commissioning_ux_operation(self, setup_params: SetupParameters): self.wait_for_user_input( prompt_msg=f"Using the DUT vendor's provided interface, commission the ICD device using the following parameters:\n" f"- discriminator: {setup_params.discriminator}\n" f"- setupPinCode: {setup_params.passcode}\n" - f"- setupQRCode: {setup_params.setup_qr_code}\n" + f"- setupQRCode: {setup_params.qr_code}\n" f"- setupManualCode: {setup_params.manual_code}\n" f"If using FabricSync Admin test app, you may type:\n" f">>> pairing onnetwork 111 {setup_params.passcode}") diff --git a/src/python_testing/TC_MCORE_FS_1_5.py b/src/python_testing/TC_MCORE_FS_1_5.py index e8d6b3e678..fc2eca6ee0 100755 --- a/src/python_testing/TC_MCORE_FS_1_5.py +++ b/src/python_testing/TC_MCORE_FS_1_5.py @@ -42,16 +42,17 @@ import logging import os import queue +import random import secrets import struct import tempfile import time -from dataclasses import dataclass import chip.clusters as Clusters from chip import ChipDeviceCtrl from chip.testing.apps import AppServerSubprocess -from chip.testing.matter_testing import MatterBaseTest, TestStep, async_test_body, default_matter_test_main, type_matches +from chip.testing.matter_testing import (MatterBaseTest, SetupParameters, TestStep, async_test_body, default_matter_test_main, + type_matches) from ecdsa.curves import NIST256p from mobly import asserts from TC_SC_3_6 import AttributeChangeAccumulator @@ -69,14 +70,6 @@ def _generate_verifier(passcode: int, salt: bytes, iterations: int) -> bytes: return w0.to_bytes(NIST256p.baselen, byteorder='big') + L.to_bytes('uncompressed') -@dataclass -class _SetupParameters: - setup_qr_code: str - manual_code: int - discriminator: int - passcode: int - - class TC_MCORE_FS_1_5(MatterBaseTest): @async_test_body async def setup_class(self): @@ -106,11 +99,8 @@ async def setup_class(self): self.dut_fsa_stdin = open(dut_fsa_stdin_pipe, "w") self.th_server_port = th_server_port - # These are default testing values. - self.th_server_setup_params = _SetupParameters( - setup_qr_code="MT:-24J0AFN00KA0648G00", - manual_code=34970112332, - discriminator=3840, + self.th_server_setup_params = SetupParameters( + discriminator=random.randint(0, 4095), passcode=20202021) # Start the TH_SERVER app. @@ -137,12 +127,12 @@ def teardown_class(self): self.storage.cleanup() super().teardown_class() - def _ask_for_vendor_commissioning_ux_operation(self, setup_params: _SetupParameters): + def _ask_for_vendor_commissioning_ux_operation(self, setup_params: SetupParameters): self.wait_for_user_input( prompt_msg=f"Using the DUT vendor's provided interface, commission the ICD device using the following parameters:\n" f"- discriminator: {setup_params.discriminator}\n" f"- setupPinCode: {setup_params.passcode}\n" - f"- setupQRCode: {setup_params.setup_qr_code}\n" + f"- setupQRCode: {setup_params.qr_code}\n" f"- setupManualCode: {setup_params.manual_code}\n" f"If using FabricSync Admin test app, you may type:\n" f">>> pairing onnetwork 111 {setup_params.passcode}") diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py index e5bdf2b3be..c176904ce1 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/matter_testing.py @@ -821,6 +821,27 @@ def __str__(self): f'\n spec_location: {self.spec_location}\n') +@dataclass +class SetupParameters: + passcode: int + vendor_id: int = 0xFFF1 + product_id: int = 0x8001 + discriminator: int = 3840 + custom_flow: int = 0 + capabilities: int = 0b0100 + version: int = 0 + + @property + def qr_code(self): + return SetupPayload().GenerateQrCode(self.passcode, self.vendor_id, self.product_id, self.discriminator, + self.custom_flow, self.capabilities, self.version) + + @property + def manual_code(self): + return SetupPayload().GenerateManualPairingCode(self.passcode, self.vendor_id, self.product_id, self.discriminator, + self.custom_flow, self.capabilities, self.version) + + @dataclass class SetupPayloadInfo: filter_type: discovery.FilterType = discovery.FilterType.LONG_DISCRIMINATOR From 53952494640d3ab06bbfb0a56b4bf10d4561d643 Mon Sep 17 00:00:00 2001 From: yeaissa <133245269+yeaissa@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:41:46 +0100 Subject: [PATCH 138/219] [NXP] Fix access to SSID array (#36704) Code is accessing the second slot of the ssid array. The size of ssid array in wifi_scan_params is set to 1 by default. Here the code is accessing the second slot of the array without taking into account the size. --- src/platform/Zephyr/wifi/WiFiManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/platform/Zephyr/wifi/WiFiManager.cpp b/src/platform/Zephyr/wifi/WiFiManager.cpp index a0730c1fa1..13188df8a4 100644 --- a/src/platform/Zephyr/wifi/WiFiManager.cpp +++ b/src/platform/Zephyr/wifi/WiFiManager.cpp @@ -216,9 +216,11 @@ CHIP_ERROR WiFiManager::Scan(const ByteSpan & ssid, ScanResultCallback resultCal memcpy(mScanSsidBuffer, ssid.data(), ssid.size()); mScanSsidBuffer[ssid.size()] = 0; // indicate the end of ssid string mScanParams.ssids[0] = mScanSsidBuffer; - mScanParams.ssids[1] = nullptr; // indicate the end of ssids list - scanParams = &mScanParams; - scanParamsSize = sizeof(*scanParams); +#if (CONFIG_WIFI_MGMT_SCAN_SSID_FILT_MAX > 1) + mScanParams.ssids[1] = nullptr; // indicate the end of ssids list +#endif + scanParams = &mScanParams; + scanParamsSize = sizeof(*scanParams); } if (0 != net_mgmt(NET_REQUEST_WIFI_SCAN, mNetIf, scanParams, scanParamsSize)) { From 9e57208880a4e7360d707697358b6cfbd84b10a3 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous <84793247+mkardous-silabs@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:14:21 -0500 Subject: [PATCH 139/219] [SIlabs] Refactor GetMacAddress function and initial clean up of the Notify functions (#36693) * Rename WifiEvent to WifiPlatformEvent * Refactor Notify function and associated data structures * Rename mac address function * Refactor Mac Address handling * Fix wf200 init * Restyled by clang-format * add init value workaroudn * Update src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h Co-authored-by: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> * start enums at 0 --------- Co-authored-by: Restyled.io Co-authored-by: Junior Martinez <67972863+jmartinez-silabs@users.noreply.github.com> --- examples/platform/silabs/efr32/BUILD.gn | 3 +- examples/platform/silabs/uart.cpp | 2 +- src/platform/silabs/CHIPDevicePlatformEvent.h | 20 --- .../silabs/ConfigurationManagerImpl.cpp | 7 +- .../silabs/ConnectivityManagerImpl_WIFI.cpp | 73 ++++----- src/platform/silabs/PlatformManagerImpl.cpp | 90 ++++------- src/platform/silabs/PlatformManagerImpl.h | 2 +- src/platform/silabs/rs911x/BLEManagerImpl.cpp | 3 - .../silabs/wifi/SiWx/WifiInterface.cpp | 77 +++++---- .../silabs/wifi/WifiInterfaceAbstraction.cpp | 134 +++++++--------- .../silabs/wifi/WifiInterfaceAbstraction.h | 147 +++++++++++------- .../silabs/wifi/lwip-support/ethernetif.cpp | 12 +- .../silabs/wifi/rs911x/WifiInterface.cpp | 81 +++++----- .../silabs/wifi/wf200/WifiInterface.cpp | 65 ++++---- src/platform/silabs/wifi/wfx_msgs.h | 12 -- .../WiseconnectInterfaceAbstraction.cpp | 38 ++--- .../WiseconnectInterfaceAbstraction.h | 20 ++- 17 files changed, 345 insertions(+), 441 deletions(-) diff --git a/examples/platform/silabs/efr32/BUILD.gn b/examples/platform/silabs/efr32/BUILD.gn index 7b9dccf7cc..46cfae71ec 100644 --- a/examples/platform/silabs/efr32/BUILD.gn +++ b/examples/platform/silabs/efr32/BUILD.gn @@ -174,7 +174,8 @@ source_set("efr32-common") { "${silabs_common_plat_dir}/syscalls_stubs.cpp", ] - if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli) { + if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli || + sl_uart_log_output) { sources += [ "${silabs_common_plat_dir}/uart.cpp" ] } diff --git a/examples/platform/silabs/uart.cpp b/examples/platform/silabs/uart.cpp index 809c4e53e0..5bf9eeb51d 100644 --- a/examples/platform/silabs/uart.cpp +++ b/examples/platform/silabs/uart.cpp @@ -53,7 +53,7 @@ extern "C" { #endif #include "sl_uartdrv_instances.h" #if SL_WIFI -#include +#include #endif // SL_WIFI #ifdef SL_CATALOG_UARTDRV_EUSART_PRESENT #include "sl_uartdrv_eusart_vcom_config.h" diff --git a/src/platform/silabs/CHIPDevicePlatformEvent.h b/src/platform/silabs/CHIPDevicePlatformEvent.h index 090ada6403..10c57a1a3b 100644 --- a/src/platform/silabs/CHIPDevicePlatformEvent.h +++ b/src/platform/silabs/CHIPDevicePlatformEvent.h @@ -63,32 +63,12 @@ struct ChipDevicePlatformEvent final #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION struct { - wfx_event_base_t eventBase; union { sl_wfx_generic_message_t genericMsgEvent; sl_wfx_startup_ind_t startupEvent; sl_wfx_connect_ind_t connectEvent; sl_wfx_disconnect_ind_t disconnectEvent; - - /* - * NOT CURRENTLY USED - *Some structs might be bigger in size than the one we use - * so we reduce the union size by commenting them out. - * Keep for possible future implementation. - */ - - // sl_wfx_generic_ind_t genericEvent; - // sl_wfx_exception_ind_t exceptionEvent; - // sl_wfx_error_ind_t errorEvent; - // sl_wfx_received_ind_t receivedEvent; - // sl_wfx_scan_result_ind_t scanResultEvent; - // sl_wfx_scan_complete_ind_t scanCompleteEvent; - // sl_wfx_start_ap_ind_t startApEvent; - // sl_wfx_stop_ap_ind_t stopApEvent; - // sl_wfx_ap_client_connected_ind_t apClientConnectedEvent; - // sl_wfx_ap_client_rejected_ind_t apClientRejectedEvent; - // sl_wfx_ap_client_disconnected_ind_t apClientDisconnectedEvent; } data; } WFXSystemEvent; #endif diff --git a/src/platform/silabs/ConfigurationManagerImpl.cpp b/src/platform/silabs/ConfigurationManagerImpl.cpp index 3a144eb116..5e38cabd4b 100644 --- a/src/platform/silabs/ConfigurationManagerImpl.cpp +++ b/src/platform/silabs/ConfigurationManagerImpl.cpp @@ -313,11 +313,10 @@ void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg) #ifdef SL_WIFI CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf) { - sl_wfx_mac_address_t macaddr; - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr); - memcpy(buf, &macaddr.octet[0], sizeof(macaddr.octet)); + VerifyOrReturnError(buf != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - return CHIP_NO_ERROR; + MutableByteSpan byteSpan(buf, kPrimaryMACAddressLength); + return GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); } #endif diff --git a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp index 0d9d63317e..441579ead0 100644 --- a/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp +++ b/src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp @@ -81,60 +81,45 @@ void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event) // Handle Wfx wifi events... if (event->Type == DeviceEventType::kWFXSystemEvent) { - if (event->Platform.WFXSystemEvent.eventBase == WIFI_EVENT) + + switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) { - switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) + case to_underlying(WifiEvent::kStartUp): + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_START"); + DriveStationState(); + break; + case to_underlying(WifiEvent::kConnect): + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED"); + if (mWiFiStationState == kWiFiStationState_Connecting) { - case SL_WFX_STARTUP_IND_ID: - ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_START"); - DriveStationState(); - break; - case SL_WFX_CONNECT_IND_ID: - ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_CONNECTED"); - if (mWiFiStationState == kWiFiStationState_Connecting) + if (event->Platform.WFXSystemEvent.data.connectEvent.body.status == 0) { - if (event->Platform.WFXSystemEvent.data.connectEvent.body.status == 0) - { - ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); - } - else - { - ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); - } + ChangeWiFiStationState(kWiFiStationState_Connecting_Succeeded); } - DriveStationState(); - break; - case SL_WFX_DISCONNECT_IND_ID: - ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_DISCONNECTED"); - if (mWiFiStationState == kWiFiStationState_Connecting) + else { ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); } - DriveStationState(); - break; - default: - break; } - } - else if (event->Platform.WFXSystemEvent.eventBase == IP_EVENT) - { - switch (event->Platform.WFXSystemEvent.data.genericMsgEvent.header.id) + DriveStationState(); + break; + case to_underlying(WifiEvent::kDisconnect): + ChipLogProgress(DeviceLayer, "WIFI_EVENT_STA_DISCONNECTED"); + if (mWiFiStationState == kWiFiStationState_Connecting) { - case IP_EVENT_STA_GOT_IP: - ChipLogProgress(DeviceLayer, "IP_EVENT_STA_GOT_IP"); - UpdateInternetConnectivityState(); - break; - case IP_EVENT_STA_LOST_IP: - ChipLogProgress(DeviceLayer, "IP_EVENT_STA_LOST_IP"); - UpdateInternetConnectivityState(); - break; - case IP_EVENT_GOT_IP6: - ChipLogProgress(DeviceLayer, "IP_EVENT_GOT_IP6"); - UpdateInternetConnectivityState(); - break; - default: - break; + ChangeWiFiStationState(kWiFiStationState_Connecting_Failed); } + DriveStationState(); + break; + + case to_underlying(WifiEvent::kGotIPv4): + case to_underlying(WifiEvent::kLostIP): + case to_underlying(WifiEvent::kGotIPv6): + ChipLogProgress(DeviceLayer, "IP Change Event"); + UpdateInternetConnectivityState(); + break; + default: + break; } } } diff --git a/src/platform/silabs/PlatformManagerImpl.cpp b/src/platform/silabs/PlatformManagerImpl.cpp index b3d7f80052..7b33b934b3 100644 --- a/src/platform/silabs/PlatformManagerImpl.cpp +++ b/src/platform/silabs/PlatformManagerImpl.cpp @@ -141,71 +141,47 @@ void PlatformManagerImpl::_Shutdown() #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION // This function needs to be global so it can be used from the platform implementation without depending on the platfrom itself. // This is a workaround to avoid a circular dependency. -void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData) +void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData) { using namespace chip; using namespace chip::DeviceLayer; ChipDeviceEvent event; memset(&event, 0, sizeof(event)); - event.Type = DeviceEventType::kWFXSystemEvent; - event.Platform.WFXSystemEvent.eventBase = eventBase; + event.Type = DeviceEventType::kWFXSystemEvent; - if (eventBase == WIFI_EVENT) + switch (eventData->header.id) { - switch (eventData->header.id) - { - case SL_WFX_STARTUP_IND_ID: - memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.startupEvent)); - break; - case SL_WFX_CONNECT_IND_ID: - memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.connectEvent)); - break; - case SL_WFX_DISCONNECT_IND_ID: - memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent)); - break; - // case SL_WFX_RECEIVED_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.receivedEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.receivedEvent)); - // break; - // case SL_WFX_GENERIC_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.genericEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.genericEvent)); - // break; - // case SL_WFX_EXCEPTION_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.exceptionEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.exceptionEvent)); - // break; - // case SL_WFX_ERROR_IND_ID: - // memcpy(&event.Platform.WFXSystemEvent.data.errorEvent, eventData, - // sizeof(event.Platform.WFXSystemEvent.data.errorEvent)); - // break; - default: - break; - } - } - else if (eventBase == IP_EVENT) - { - switch (eventData->header.id) - { - case IP_EVENT_STA_GOT_IP: - memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); - break; - case IP_EVENT_GOT_IP6: - memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); - break; - case IP_EVENT_STA_LOST_IP: - memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, - sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); - break; - default: - break; - } +// TODO: Work around until we unify the data structures behind a Matter level common structure +#if WF200_WIFI + case SL_WFX_STARTUP_IND_ID: +#endif + case to_underlying(WifiEvent::kStartUp): + memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.startupEvent)); + // TODO: This is a workaround until we unify the Matter Data structures + event.Platform.WFXSystemEvent.data.startupEvent.header.id = to_underlying(WifiEvent::kStartUp); + break; + + case to_underlying(WifiEvent::kConnect): + memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.connectEvent)); + break; + + case to_underlying(WifiEvent::kDisconnect): + memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent)); + break; + + case to_underlying(WifiEvent::kGotIPv4): + case to_underlying(WifiEvent::kLostIP): + case to_underlying(WifiEvent::kGotIPv6): + memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData, + sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent)); + break; + + default: + break; } // TODO: We should add error processing here diff --git a/src/platform/silabs/PlatformManagerImpl.h b/src/platform/silabs/PlatformManagerImpl.h index dddc491384..ee5897bbf1 100644 --- a/src/platform/silabs/PlatformManagerImpl.h +++ b/src/platform/silabs/PlatformManagerImpl.h @@ -31,7 +31,7 @@ #include #if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION -void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData); #endif namespace chip { diff --git a/src/platform/silabs/rs911x/BLEManagerImpl.cpp b/src/platform/silabs/rs911x/BLEManagerImpl.cpp index 75f118b38a..90103f74e7 100644 --- a/src/platform/silabs/rs911x/BLEManagerImpl.cpp +++ b/src/platform/silabs/rs911x/BLEManagerImpl.cpp @@ -699,9 +699,6 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) mFlags.Clear(Flags::kRestartAdvertising); - sl_wfx_mac_address_t macaddr; - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr); - status = sInstance.SendBLEAdvertisementCommand(); if (status == RSI_SUCCESS) diff --git a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp index 291c9988d8..7ff167fc71 100644 --- a/src/platform/silabs/wifi/SiWx/WifiInterface.cpp +++ b/src/platform/silabs/wifi/SiWx/WifiInterface.cpp @@ -196,7 +196,7 @@ constexpr uint16_t kWifiScanTimeoutTicks = 10000; void DHCPTimerEventHandler(void * arg) { - WifiEvent event = WifiEvent::kStationDhcpPoll; + WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpPoll; sl_matter_wifi_post_event(event); } @@ -257,7 +257,7 @@ sl_status_t sl_wifi_siwx917_init(void) ChipLogDetail(DeviceLayer, "Firmware version is: %x%x.%d.%d.%d.%d.%d.%d", version.chip_id, version.rom_id, version.major, version.minor, version.security_version, version.patch_num, version.customer_id, version.build_num); - status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, (sl_mac_address_t *) &wfx_rsi.sta_mac.octet[0]); + status = sl_wifi_get_mac_address(SL_WIFI_CLIENT_INTERFACE, reinterpret_cast(wfx_rsi.sta_mac.data())); VerifyOrReturnError(status == SL_STATUS_OK, status, ChipLogError(DeviceLayer, "sl_wifi_get_mac_address failed: 0x%lx", static_cast(status))); @@ -300,7 +300,7 @@ sl_status_t ScanCallback(sl_wifi_event_t event, sl_wifi_scan_result_t * scan_res { security = static_cast(scan_result->scan_info[0].security_mode); wfx_rsi.ap_chan = scan_result->scan_info[0].rf_channel; - memcpy(&wfx_rsi.ap_mac.octet, scan_result->scan_info[0].bssid, BSSID_LEN); + memcpy(wfx_rsi.ap_mac.data(), scan_result->scan_info[0].bssid, kWifiMacAddressLength); } osSemaphoreRelease(sScanCompleteSemaphore); @@ -410,7 +410,7 @@ sl_status_t JoinWifiNetwork(void) if (status == SL_STATUS_OK || status == SL_STATUS_IN_PROGRESS) { - WifiEvent event = WifiEvent::kStationConnect; + WifiPlatformEvent event = WifiPlatformEvent::kStationConnect; sl_matter_wifi_post_event(event); return status; } @@ -424,7 +424,7 @@ sl_status_t JoinWifiNetwork(void) ChipLogProgress(DeviceLayer, "Connection retry attempt %d", wfx_rsi.join_retries); wfx_retry_connection(++wfx_rsi.join_retries); - WifiEvent event = WifiEvent::kStationStartJoin; + WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; sl_matter_wifi_post_event(event); return status; @@ -453,7 +453,7 @@ sl_status_t sl_matter_wifi_platform_init(void) VerifyOrReturnError(sScanCompleteSemaphore != nullptr, SL_STATUS_ALLOCATION_FAILED); // Create the message queue - sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WifiEvent), nullptr); + sWifiEventQueue = osMessageQueueNew(kWfxQueueSize, sizeof(WifiPlatformEvent), nullptr); VerifyOrReturnError(sWifiEventQueue != nullptr, SL_STATUS_ALLOCATION_FAILED); // Create timer for DHCP polling @@ -480,7 +480,7 @@ int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap) ap->security = wfx_rsi.sec.security; ap->chan = wfx_rsi.ap_chan; chip::Platform::CopyString(ap->ssid, ap->ssid_length, wfx_rsi.sec.ssid); - memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_LEN); + memcpy(&ap->bssid[0], wfx_rsi.ap_mac.data(), kWifiMacAddressLength); sl_wifi_get_signal_strength(SL_WIFI_CLIENT_INTERFACE, &rssi); ap->rssi = rssi; return status; @@ -570,7 +570,7 @@ sl_status_t show_scan_results(sl_wifi_scan_result_t * scan_result) } cur_scan_result.security = static_cast(scan_result->scan_info[idx].security_mode); cur_scan_result.rssi = (-1) * scan_result->scan_info[idx].rssi_val; - memcpy(cur_scan_result.bssid, scan_result->scan_info[idx].bssid, BSSID_LEN); + memcpy(cur_scan_result.bssid, scan_result->scan_info[idx].bssid, kWifiMacAddressLength); wfx_rsi.scan_cb(&cur_scan_result); // if user has not provided the ssid, then call the callback for each scan result @@ -606,13 +606,13 @@ sl_status_t bg_scan_callback_handler(sl_wifi_event_t event, sl_wifi_scan_result_ void NotifyConnectivity(void) { VerifyOrReturn(!hasNotifiedWifiConnectivity); - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac); + NotifyConnection(wfx_rsi.ap_mac); hasNotifiedWifiConnectivity = true; } void HandleDHCPPolling(void) { - WifiEvent event; + WifiPlatformEvent event; // TODO: Notify the application that the interface is not set up or Chipdie here because we are in an unkonwn state struct netif * sta_netif = &wifi_client_context.netif; @@ -624,13 +624,13 @@ void HandleDHCPPolling(void) { wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr); hasNotifiedIPV4 = true; - event = WifiEvent::kStationDhcpDone; + event = WifiPlatformEvent::kStationDhcpDone; sl_matter_wifi_post_event(event); NotifyConnectivity(); } else if (dhcp_state == DHCP_OFF) { - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ @@ -642,14 +642,14 @@ void HandleDHCPPolling(void) char addrStr[chip::Inet::IPAddress::kMaxStringLength] = { 0 }; VerifyOrReturn(ip6addr_ntoa_r(netif_ip6_addr(sta_netif, 0), addrStr, sizeof(addrStr)) != nullptr); ChipLogProgress(DeviceLayer, "SLAAC OK: linklocal addr: %s", addrStr); - wfx_ipv6_notify(GET_IPV6_SUCCESS); + NotifyIPv6Change(true); hasNotifiedIPV6 = true; - event = WifiEvent::kStationDhcpDone; + event = WifiPlatformEvent::kStationDhcpDone; sl_matter_wifi_post_event(event); NotifyConnectivity(); } } -void sl_matter_wifi_post_event(WifiEvent event) +void sl_matter_wifi_post_event(WifiPlatformEvent event) { sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); @@ -662,7 +662,7 @@ void sl_matter_wifi_post_event(WifiEvent event) } /// ResetDHCPNotificationFlags /// @brief Reset the flags that are used to notify the application about DHCP connectivity -/// and emits a WifiEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. +/// and emits a WifiPlatformEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. void ResetDHCPNotificationFlags(void) { @@ -672,23 +672,23 @@ void ResetDHCPNotificationFlags(void) hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; - WifiEvent event = WifiEvent::kStationDoDhcp; + WifiPlatformEvent event = WifiPlatformEvent::kStationDoDhcp; sl_matter_wifi_post_event(event); } -void ProcessEvent(WifiEvent event) +void ProcessEvent(WifiPlatformEvent event) { // Process event switch (event) { - case WifiEvent::kStationConnect: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationConnect"); + case WifiPlatformEvent::kStationConnect: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationConnect"); wfx_rsi.dev_state.Set(WifiState::kStationConnected); ResetDHCPNotificationFlags(); break; - case WifiEvent::kStationDisconnect: { - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDisconnect"); + case WifiPlatformEvent::kStationDisconnect: { + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDisconnect"); // TODO: This event is not being posted anywhere, seems to be a dead code or we are missing something wfx_rsi.dev_state.Clear(WifiState::kStationReady) @@ -699,24 +699,23 @@ void ProcessEvent(WifiEvent event) /* TODO: Implement disconnect notify */ ResetDHCPNotificationFlags(); #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(0); // for IPV4 - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); } break; - case WifiEvent::kAPStart: + case WifiPlatformEvent::kAPStart: // TODO: Currently unimplemented break; - case WifiEvent::kScan: - ChipLogDetail(DeviceLayer, "WifiEvent::kScan"); + case WifiPlatformEvent::kScan: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan"); #ifdef SL_WFX_CONFIG_SCAN if (!(wfx_rsi.dev_state.Has(WifiState::kScanStarted))) { - ChipLogDetail(DeviceLayer, "WifiEvent::kScan"); + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kScan"); sl_wifi_scan_configuration_t wifi_scan_configuration; memset(&wifi_scan_configuration, 0, sizeof(wifi_scan_configuration)); @@ -761,25 +760,25 @@ void ProcessEvent(WifiEvent event) #endif /* SL_WFX_CONFIG_SCAN */ break; - case WifiEvent::kStationStartJoin: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationStartJoin"); + case WifiPlatformEvent::kStationStartJoin: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationStartJoin"); InitiateScan(); JoinWifiNetwork(); break; - case WifiEvent::kStationDoDhcp: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDoDhcp"); + case WifiPlatformEvent::kStationDoDhcp: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDoDhcp"); StartDHCPTimer(WFX_RSI_DHCP_POLL_INTERVAL); break; - case WifiEvent::kStationDhcpDone: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDhcpDone"); + case WifiPlatformEvent::kStationDhcpDone: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDhcpDone"); CancelDHCPTimer(); break; - case WifiEvent::kStationDhcpPoll: - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDhcpPoll"); + case WifiPlatformEvent::kStationDhcpPoll: + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDhcpPoll"); HandleDHCPPolling(); break; @@ -802,7 +801,7 @@ void ProcessEvent(WifiEvent event) void sl_matter_wifi_task(void * arg) { (void) arg; - WifiEvent event; + WifiPlatformEvent event; sl_status_t status = SL_STATUS_OK; status = sl_wifi_siwx917_init(); @@ -848,7 +847,7 @@ void wfx_dhcp_got_ipv4(uint32_t ip) wfx_rsi.ip4_addr[3]); /* Notify the Connectivity Manager - via the app */ wfx_rsi.dev_state.Set(WifiState::kStationDhcpDone).Set(WifiState::kStationReady); - wfx_ip_changed_notify(IP_STATUS_SUCCESS); + NotifyIPv4Change(true); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp index 698c839a10..d6ea0beca7 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,7 @@ using namespace chip::DeviceLayer; // TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation. // As such we can't depend on the platform here as well -extern void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +extern void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData); namespace { @@ -61,109 +62,82 @@ void RetryConnectionTimerHandler(void * arg) } // namespace -/*********************************************************************************** - * @fn sl_matter_wifi_task_started(void) - * @brief - * Wifi device started notification - * @param[in]: None - * @return None - *************************************************************************************/ -void sl_matter_wifi_task_started(void) +/* Updated functions */ + +void NotifyIPv6Change(bool gotIPv6Addr) { - sl_wfx_startup_ind_t evt; - sl_wfx_mac_address_t mac; + sl_wfx_generic_message_t eventData = {}; + eventData.header.id = gotIPv6Addr ? to_underlying(WifiEvent::kGotIPv6) : to_underlying(WifiEvent::kLostIP); + eventData.header.length = sizeof(eventData.header); - // Creating a timer which will be used to retry connection with AP - sRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL); - VerifyOrReturn(sRetryTimer != NULL); + HandleWFXSystemEvent(&eventData); +} - memset(&evt, 0, sizeof(evt)); - evt.header.id = SL_WFX_STARTUP_IND_ID; - evt.header.length = sizeof evt; - evt.body.status = 0; - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac); - memcpy(&evt.body.mac_addr[0], &mac.octet[0], MAC_ADDRESS_FIRST_OCTET); +void NotifyIPv4Change(bool gotIPv4Addr) +{ + sl_wfx_generic_message_t eventData; - HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt); + memset(&eventData, 0, sizeof(eventData)); + eventData.header.id = gotIPv4Addr ? to_underlying(WifiEvent::kGotIPv4) : to_underlying(WifiEvent::kLostIP); + eventData.header.length = sizeof(eventData.header); + HandleWFXSystemEvent(&eventData); } -/*********************************************************************************** - * @fn void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t *ap) - * @brief - * For now we are not notifying anything other than AP Mac - - * Other stuff such as DTIM etc. may be required for later - * @param[in] status: - * @param[in] ap: access point - * @return None - *************************************************************************************/ -void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap) +void NotifyDisconnection(WifiDisconnectionReasons reason) { - sl_wfx_connect_ind_t evt; - - VerifyOrReturn(status == SUCCESS_STATUS); + sl_wfx_disconnect_ind_t evt = {}; + evt.header.id = to_underlying(WifiEvent::kDisconnect); + evt.header.length = sizeof evt; + evt.body.reason = to_underlying(reason); - memset(&evt, 0, sizeof(evt)); - evt.header.id = SL_WFX_CONNECT_IND_ID; - evt.header.length = sizeof evt; + HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); +} +void NotifyConnection(const MacAddress & ap) +{ + sl_wfx_connect_ind_t evt = {}; + evt.header.id = to_underlying(WifiEvent::kConnect); + evt.header.length = sizeof evt; #ifdef RS911X_WIFI evt.body.channel = wfx_rsi.ap_chan; #endif - memcpy(&evt.body.mac[0], &ap->octet[0], MAC_ADDRESS_FIRST_OCTET); + std::copy(ap.begin(), ap.end(), evt.body.mac); - HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt); + HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); } -/************************************************************************************** - * @fn void wfx_disconnected_notify(int32_t status) +/* Function to update */ + +/*********************************************************************************** + * @fn sl_matter_wifi_task_started(void) * @brief - * notification of disconnection - * @param[in] status: + * Wifi device started notification + * @param[in]: None * @return None *************************************************************************************/ -void wfx_disconnected_notify(int32_t status) +void sl_matter_wifi_task_started(void) { - sl_wfx_disconnect_ind_t evt; + sl_wfx_startup_ind_t evt = {}; - memset(&evt, 0, sizeof(evt)); - evt.header.id = SL_WFX_DISCONNECT_IND_ID; - evt.header.length = sizeof evt; - evt.body.reason = status; - HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt); -} + // Creating a timer which will be used to retry connection with AP + sRetryTimer = osTimerNew(RetryConnectionTimerHandler, osTimerOnce, NULL, NULL); + VerifyOrReturn(sRetryTimer != NULL); -/************************************************************************************** - * @fn void wfx_ipv6_notify(int got_ip) - * @brief - * notification of ipv6 - * @param[in] got_ip: - * @return None - *************************************************************************************/ -void wfx_ipv6_notify(int got_ip) -{ - sl_wfx_generic_message_t eventData; + evt.header.id = to_underlying(WifiEvent::kStartUp); + evt.header.length = sizeof evt; + evt.body.status = 0; - memset(&eventData, 0, sizeof(eventData)); - eventData.header.id = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP; - eventData.header.length = sizeof(eventData.header); - HandleWFXSystemEvent(IP_EVENT, &eventData); -} + // TODO : Remove workwound when sl_wfx_startup_ind_t is unified + // Issue is same structure name but different contents +#if WF200_WIFI + MutableByteSpan macSpan(evt.body.mac_addr[SL_WFX_STA_INTERFACE], kWifiMacAddressLength); +#else + MutableByteSpan macSpan(evt.body.mac_addr, kWifiMacAddressLength); +#endif // WF200_WIFI -/************************************************************************************** - * @fn void wfx_ip_changed_notify(int got_ip) - * @brief - * notification of ip change - * @param[in] got_ip: - * @return None - *************************************************************************************/ -void wfx_ip_changed_notify(int got_ip) -{ - sl_wfx_generic_message_t eventData; + GetMacAddress(SL_WFX_STA_INTERFACE, macSpan); - memset(&eventData, 0, sizeof(eventData)); - eventData.header.id = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP; - eventData.header.length = sizeof(eventData.header); - HandleWFXSystemEvent(IP_EVENT, &eventData); + HandleWFXSystemEvent((sl_wfx_generic_message_t *) &evt); } /************************************************************************************** diff --git a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h index 012683aef6..f89f3fefed 100644 --- a/src/platform/silabs/wifi/WifiInterfaceAbstraction.h +++ b/src/platform/silabs/wifi/WifiInterfaceAbstraction.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -36,35 +37,41 @@ #include "sl_si91x_types.h" #include "sl_wifi_constants.h" #include "sl_wifi_device.h" +#endif // (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) -/* - * Interface to RSI Sapis - */ +/* Updated constants */ -#define WFX_RSI_DHCP_POLL_INTERVAL (250) /* Poll interval in ms for DHCP */ +constexpr size_t kWifiMacAddressLength = 6; -// MAX SSID LENGTH excluding NULL character -#define WFX_MAX_SSID_LENGTH (32) +/* Defines to update */ + +// TODO: Not sure why the pass key max length differs for the 917 SoC & NCP +#if (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) // MAX PASSKEY LENGTH including NULL character #define WFX_MAX_PASSKEY_LENGTH (SL_WIFI_MAX_PSK_LENGTH) -#define SL_WIFI_ALLOCATE_COMMAND_BUFFER_WAIT_TIME_MS (1000) #else -// MAX SSID LENGTH excluding NULL character -#define WFX_MAX_SSID_LENGTH (32) // MAX PASSKEY LENGTH including NULL character #define WFX_MAX_PASSKEY_LENGTH (64) #endif // (SLI_SI91X_MCU_INTERFACE | EXP_BOARD) +// MAX SSID LENGTH excluding NULL character +#define WFX_MAX_SSID_LENGTH (32) #define MAX_JOIN_RETRIES_COUNT (5) -#define BSSID_LEN (6) -#define MAC_ADDRESS_FIRST_OCTET (6) -#define CONNECTION_STATUS_SUCCESS (1) -#define IP_STATUS_FAIL (0) -#define GET_IPV6_FAIL (0) -#define IP_STATUS_SUCCESS (1) -// TASK and Interrupt Macros -#define SUCCESS_STATUS (1) +/* Updated types */ + +using MacAddress = std::array; + +enum class WifiEvent : uint8_t +{ + kStartUp = 0, + kConnect = 1, + kDisconnect = 2, + kScanComplete = 3, + kGotIPv4 = 4, + kGotIPv6 = 5, + kLostIP = 6, +}; enum class WifiState : uint16_t { @@ -81,24 +88,16 @@ enum class WifiState : uint16_t kScanStarted = (1 << 10), /* Scan Started */ }; -enum class WifiEvent : uint8_t +enum class WifiDisconnectionReasons : uint16_t // using uint16 to match current structure during the transition { - kStationConnect = 0, - kStationDisconnect = 1, - kAPStart = 2, - kAPStop = 3, - kScan = 4, /* This is used as scan result and start */ - kStationStartJoin = 5, - kStationDoDhcp = 6, - kStationDhcpDone = 7, - kStationDhcpPoll = 8 + kUnknownError = 1, // Disconnation due to an internal error + kAccessPointLost = 2, // Device did not receive AP beacon too many times + kAccessPoint = 3, // AP disconnected the device + kApplication = 4, // Application requested disconnection + kWPACouterMeasures = 5, // WPA contermeasures triggered a disconnection }; -typedef enum -{ - WIFI_EVENT, - IP_EVENT, -} wfx_event_base_t; +/* Enums to update */ /* Note that these are same as RSI_security */ typedef enum @@ -135,7 +134,7 @@ typedef struct wfx_wifi_scan_result char ssid[WFX_MAX_SSID_LENGTH + 1]; size_t ssid_length; wfx_sec_t security; - uint8_t bssid[BSSID_LEN]; + uint8_t bssid[kWifiMacAddressLength]; uint8_t chan; int16_t rssi; /* I suspect this is in dBm - so signed */ } wfx_wifi_scan_result_t; @@ -151,13 +150,6 @@ typedef struct wfx_wifi_scan_ext uint32_t overrun_count; } wfx_wifi_scan_ext_t; -typedef enum -{ - IP_EVENT_STA_GOT_IP, - IP_EVENT_GOT_IP6, - IP_EVENT_STA_LOST_IP, -} ip_event_id_t; - #ifdef RS911X_WIFI /* * This Sh%t is here to support WFXUtils - and the Matter stuff that uses it @@ -181,11 +173,11 @@ typedef struct wfx_rsi_s size_t scan_ssid_length; #endif #ifdef SL_WFX_CONFIG_SOFTAP - sl_wfx_mac_address_t softap_mac; + MacAddress softap_mac; #endif - sl_wfx_mac_address_t sta_mac; - sl_wfx_mac_address_t ap_mac; /* To which our STA is connected */ - sl_wfx_mac_address_t ap_bssid; /* To which our STA is connected */ + MacAddress sta_mac; + MacAddress ap_mac; /* To which our STA is connected */ + MacAddress ap_bssid; /* To which our STA is connected */ uint16_t join_retries; uint8_t ip4_addr[4]; /* Not sure if this is enough */ } WfxRsi_t; @@ -193,9 +185,59 @@ typedef struct wfx_rsi_s // TODO: We shouldn't need to have access to a global variable in the interface here extern WfxRsi_t wfx_rsi; +/* Updated functions */ + +/** + * @brief Function notifies the PlatformManager that an IPv6 event occured on the WiFi interface. + * + * @param gotIPv6Addr true, got an IPv6 address + * false, lost or wasn't able to get an IPv6 address + */ +void NotifyIPv6Change(bool gotIPv6Addr); + +#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 +/** + * @brief Function notifies the PlatformManager that an IPv4 event occured on the WiFi interface. + * + * @param gotIPv4Addr true, got an IPv4 address + * false, lost or wasn't able to get an IPv4 address + */ +void NotifyIPv4Change(bool gotIPv4Addr); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ + +/** + * @brief Function notifies the PlatformManager that a disconnection event occurred + * + * @param reason reason for the disconnection + */ +void NotifyDisconnection(WifiDisconnectionReasons reason); + +/** + * @brief Function notifies the PlatformManager that a connection event occurred + * + * @param[in] ap pointer to the structure that contains the MAC address of the AP + */ +void NotifyConnection(const MacAddress & ap); + +/** + * @brief Returns the provide interfaces MAC address + * Valid buffer large enough for the MAC address must be provided to the function + * + * @param[in] interface SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE. + * If soft AP is not enabled, the interface is ignored and the function always returns the Station MAC + * address + * @param[out] addr Interface MAC addres + * + * @return CHIP_ERROR CHIP_NO_ERROR on success + * CHIP_ERROR_BUFFER_TOO_SMALL if the provided ByteSpan size is too small + * + */ +CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & addr); + +/* Function to update */ + sl_status_t wfx_wifi_start(void); void wfx_enable_sta_mode(void); -void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr); void wfx_set_wifi_provision(wfx_wifi_provision_t * wifiConfig); bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig); bool wfx_is_sta_mode_enabled(void); @@ -221,8 +263,6 @@ void wfx_cancel_scan(void); * Call backs into the Matter Platform code */ void sl_matter_wifi_task_started(void); -void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap); -void wfx_disconnected_notify(int32_t status); /* Implemented for LWIP */ void wfx_lwip_set_sta_link_up(void); @@ -232,9 +272,7 @@ struct netif * wfx_get_netif(sl_wfx_interface_t interface); #if CHIP_DEVICE_CONFIG_ENABLE_IPV4 void wfx_dhcp_got_ipv4(uint32_t); -void wfx_ip_changed_notify(int got_ip); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ -void wfx_ipv6_notify(int got_ip); void wfx_retry_connection(uint16_t retryAttempt); #ifdef RS911X_WIFI @@ -261,22 +299,11 @@ sl_status_t wfx_power_save(); void sl_matter_wifi_task(void * arg); -#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -void wfx_ip_changed_notify(int got_ip); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap); int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info); int32_t wfx_rsi_reset_count(); int32_t sl_wifi_platform_disconnect(); -/** - * @brief Posts an event to the Wi-Fi task - * - * @param[in] event Event to process. - */ -void sl_matter_wifi_post_event(WifiEvent event); - #ifdef __cplusplus extern "C" { #endif diff --git a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp index c37d6ab933..9d9115ba42 100644 --- a/src/platform/silabs/wifi/lwip-support/ethernetif.cpp +++ b/src/platform/silabs/wifi/lwip-support/ethernetif.cpp @@ -88,16 +88,8 @@ static void low_level_init(struct netif * netif) netif->hwaddr_len = ETH_HWADDR_LEN; /* Set netif MAC hardware address */ - sl_wfx_mac_address_t mac_addr; - - wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac_addr); - - netif->hwaddr[0] = mac_addr.octet[0]; - netif->hwaddr[1] = mac_addr.octet[1]; - netif->hwaddr[2] = mac_addr.octet[2]; - netif->hwaddr[3] = mac_addr.octet[3]; - netif->hwaddr[4] = mac_addr.octet[4]; - netif->hwaddr[5] = mac_addr.octet[5]; + chip::MutableByteSpan byteSpan(netif->hwaddr, ETH_HWADDR_LEN); + GetMacAddress(SL_WFX_STA_INTERFACE, byteSpan); /* Set netif maximum transfer unit */ netif->mtu = 1500; diff --git a/src/platform/silabs/wifi/rs911x/WifiInterface.cpp b/src/platform/silabs/wifi/rs911x/WifiInterface.cpp index 8b811534ca..fa0fac5482 100644 --- a/src/platform/silabs/wifi/rs911x/WifiInterface.cpp +++ b/src/platform/silabs/wifi/rs911x/WifiInterface.cpp @@ -104,7 +104,7 @@ static void rsi_wireless_driver_task_wrapper(void * argument) static void DHCPTimerEventHandler(void * arg) { - WifiEvent event = WifiEvent::kStationDhcpPoll; + WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpPoll; sl_matter_wifi_post_event(event); } @@ -154,7 +154,7 @@ int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap) uint8_t rssi; ap->security = wfx_rsi.sec.security; ap->chan = wfx_rsi.ap_chan; - memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_LEN); + memcpy(&ap->bssid[0], wfx_rsi.ap_mac.data(), kWifiMacAddressLength); status = rsi_wlan_get(RSI_RSSI, &rssi, sizeof(rssi)); if (status == RSI_SUCCESS) { @@ -262,7 +262,7 @@ static void wfx_rsi_join_cb(uint16_t status, const uint8_t * buf, const uint16_t */ ChipLogProgress(DeviceLayer, "wfx_rsi_join_cb: success"); memset(&temp_reset, 0, sizeof(wfx_wifi_scan_ext_t)); - WifiEvent event = WifiEvent::kStationConnect; + WifiPlatformEvent event = WifiPlatformEvent::kStationConnect; sl_matter_wifi_post_event(event); wfx_rsi.join_retries = 0; } @@ -284,7 +284,7 @@ static void wfx_rsi_join_fail_cb(uint16_t status, uint8_t * buf, uint32_t len) wfx_rsi.dev_state.Clear(WifiState::kStationConnecting).Clear(WifiState::kStationConnected); - WifiEvent event = WifiEvent::kStationStartJoin; + WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; sl_matter_wifi_post_event(event); } /************************************************************************************* @@ -375,17 +375,17 @@ static int32_t sl_matter_wifi_init(void) /* initializes wlan radio parameters and WLAN supplicant parameters. */ (void) rsi_wlan_radio_init(); /* Required so we can get MAC address */ - if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, &wfx_rsi.sta_mac.octet[0], RESP_BUFF_SIZE)) != RSI_SUCCESS) + if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, wfx_rsi.sta_mac.data(), RESP_BUFF_SIZE)) != RSI_SUCCESS) { ChipLogError(DeviceLayer, "rsi_wlan_get(RSI_MAC_ADDRESS) failed: %ld", status); return status; } - ChipLogDetail(DeviceLayer, "MAC: %02x:%02x:%02x %02x:%02x:%02x", wfx_rsi.sta_mac.octet[0], wfx_rsi.sta_mac.octet[1], - wfx_rsi.sta_mac.octet[2], wfx_rsi.sta_mac.octet[3], wfx_rsi.sta_mac.octet[4], wfx_rsi.sta_mac.octet[5]); + ChipLogDetail(DeviceLayer, "MAC: %02x:%02x:%02x %02x:%02x:%02x", wfx_rsi.sta_mac.at(0), wfx_rsi.sta_mac.at(1), + wfx_rsi.sta_mac.at(2), wfx_rsi.sta_mac.at(3), wfx_rsi.sta_mac.at(4), wfx_rsi.sta_mac.at(5)); // Create the message queue - sWifiEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WifiEvent), NULL); + sWifiEventQueue = osMessageQueueNew(WFX_QUEUE_SIZE, sizeof(WifiPlatformEvent), NULL); if (sWifiEventQueue == NULL) { return SL_STATUS_ALLOCATION_FAILED; @@ -451,7 +451,7 @@ static void wfx_rsi_save_ap_info(void) // translation } wfx_rsi.sec.security = WFX_SEC_UNSPECIFIED; wfx_rsi.ap_chan = rsp.scan_info->rf_channel; - memcpy(&wfx_rsi.ap_mac.octet[0], &rsp.scan_info->bssid[0], BSSID_LEN); + memcpy(wfx_rsi.ap_mac.data(), &rsp.scan_info->bssid[0], kWifiMacAddressLength); switch (rsp.scan_info->security_mode) { @@ -563,7 +563,7 @@ void NotifyConnectivity(void) { if (!hasNotifiedWifiConnectivity) { - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac); + NotifyConnection(wfx_rsi.ap_mac); hasNotifiedWifiConnectivity = true; } } @@ -590,7 +590,7 @@ void HandleDHCPPolling(void) } else if (dhcp_state == DHCP_OFF) { - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ @@ -599,9 +599,9 @@ void HandleDHCPPolling(void) */ if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) { - wfx_ipv6_notify(GET_IPV6_SUCCESS); - hasNotifiedIPV6 = true; - WifiEvent event = WifiEvent::kStationDhcpDone; + NotifyIPv6Change(true); + hasNotifiedIPV6 = true; + WifiPlatformEvent event = WifiPlatformEvent::kStationDhcpDone; sl_matter_wifi_post_event(event); NotifyConnectivity(); } @@ -609,11 +609,11 @@ void HandleDHCPPolling(void) /** ResetDHCPNotificationFlags * @brief Reset the flags that are used to notify the application about DHCP connectivity - * and emits a WifiEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. + * and emits a WifiPlatformEvent::kStationDoDhcp event to trigger DHCP polling checks. Helper function for ProcessEvent. */ void ResetDHCPNotificationFlags(void) { - WifiEvent outEvent; + WifiPlatformEvent outEvent; #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) hasNotifiedIPV4 = false; @@ -621,11 +621,11 @@ void ResetDHCPNotificationFlags(void) hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; - outEvent = WifiEvent::kStationDoDhcp; + outEvent = WifiPlatformEvent::kStationDoDhcp; sl_matter_wifi_post_event(outEvent); } -void sl_matter_wifi_post_event(WifiEvent event) +void sl_matter_wifi_post_event(WifiPlatformEvent event) { sl_status_t status = osMessageQueuePut(sWifiEventQueue, &event, 0, 0); @@ -645,43 +645,38 @@ void sl_matter_wifi_post_event(WifiEvent event) * * @param event The input Wi-Fi event to be processed. */ -void ProcessEvent(WifiEvent event) +void ProcessEvent(WifiPlatformEvent event) { // Process event switch (event) { - case WifiEvent::kStationConnect: { - ChipLogDetail(DeviceLayer, "WifiEvent::kStationConnect"); + case WifiPlatformEvent::kStationConnect: { + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationConnect"); wfx_rsi.dev_state.Set(WifiState::kStationConnected); ResetDHCPNotificationFlags(); wfx_lwip_set_sta_link_up(); - /* We need to get AP Mac - TODO */ - // Uncomment once the hook into MATTER is moved to IP connectivty instead - // of AP connectivity. - // wfx_connected_notify(0, &wfx_rsi.ap_mac); // This - // is independant of IP connectivity. } break; - case WifiEvent::kStationDisconnect: { - ChipLogDetail(DeviceLayer, "WifiEvent::kStationDisconnect"); + case WifiPlatformEvent::kStationDisconnect: { + ChipLogDetail(DeviceLayer, "WifiPlatformEvent::kStationDisconnect"); // TODO: This event is not being posted anywhere, seems to be a dead code or we are missing something WifiStateFlags flagsToClear = WifiStateFlags(WifiState::kStationReady, WifiState::kStationConnecting, WifiState::kStationConnected, WifiState::kStationDhcpDone); wfx_rsi.dev_state.Clear(flagsToClear); /* TODO: Implement disconnect notify */ ResetDHCPNotificationFlags(); - wfx_lwip_set_sta_link_down(); // Internally dhcpclient_poll(netif) -> - // wfx_ip_changed_notify(0) for IPV4 + wfx_lwip_set_sta_link_down(); + #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); } break; - case WifiEvent::kAPStart: + case WifiPlatformEvent::kAPStart: // TODO: Currently unimplemented break; - case WifiEvent::kScan: { + case WifiPlatformEvent::kScan: { #ifdef SL_WFX_CONFIG_SCAN rsi_rsp_scan_t scan_rsp = { 0 }; memset(&scan_rsp, 0, sizeof(scan_rsp)); @@ -720,9 +715,9 @@ void ProcessEvent(WifiEvent event) ap.security = static_cast(scan->security_mode); ap.rssi = (-1) * scan->rssi_val; - configASSERT(sizeof(ap.bssid) == BSSID_LEN); - configASSERT(sizeof(scan->bssid) == BSSID_LEN); - memcpy(ap.bssid, scan->bssid, BSSID_LEN); + configASSERT(sizeof(ap.bssid) == kWifiMacAddressLength); + configASSERT(sizeof(scan->bssid) == kWifiMacAddressLength); + memcpy(ap.bssid, scan->bssid, kWifiMacAddressLength); (*wfx_rsi.scan_cb)(&ap); // no ssid filter set, return all results @@ -746,22 +741,22 @@ void ProcessEvent(WifiEvent event) #endif /* SL_WFX_CONFIG_SCAN */ } break; - case WifiEvent::kStationStartJoin: { + case WifiPlatformEvent::kStationStartJoin: { // saving the AP related info wfx_rsi_save_ap_info(); // Joining to the network sl_wifi_platform_join_network(); } break; - case WifiEvent::kStationDoDhcp: { + case WifiPlatformEvent::kStationDoDhcp: { StartDHCPTimer(WFX_RSI_DHCP_POLL_INTERVAL); } break; - case WifiEvent::kStationDhcpDone: { + case WifiPlatformEvent::kStationDhcpDone: { CancelDHCPTimer(); } break; - case WifiEvent::kStationDhcpPoll: { + case WifiPlatformEvent::kStationDhcpPoll: { HandleDHCPPolling(); } break; @@ -790,7 +785,7 @@ void sl_matter_wifi_task(void * arg) ChipLogError(DeviceLayer, "sl_matter_wifi_task: sl_matter_wifi_init failed: %ld", rsi_status); return; } - WifiEvent event; + WifiPlatformEvent event; sl_matter_lwip_start(); sl_matter_wifi_task_started(); @@ -831,7 +826,7 @@ void wfx_dhcp_got_ipv4(uint32_t ip) wfx_rsi.ip4_addr[3]); /* Notify the Connectivity Manager - via the app */ wfx_rsi.dev_state.Set(WifiState::kStationDhcpDone, WifiState::kStationReady); - wfx_ip_changed_notify(IP_STATUS_SUCCESS); + NotifyIPv4Change(true); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ diff --git a/src/platform/silabs/wifi/wf200/WifiInterface.cpp b/src/platform/silabs/wifi/wf200/WifiInterface.cpp index 1ff37ab617..d93bb17011 100644 --- a/src/platform/silabs/wifi/wf200/WifiInterface.cpp +++ b/src/platform/silabs/wifi/wf200/WifiInterface.cpp @@ -45,7 +45,7 @@ using namespace ::chip::DeviceLayer; // TODO: This is a workaround because we depend on the platform lib which depends on the platform implementation. // As such we can't depend on the platform here as well -extern void HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData); +extern void HandleWFXSystemEvent(sl_wfx_generic_message_t * eventData); /* wfxRsi Task will use as its stack */ StackType_t wfxEventTaskStack[1024] = { 0 }; @@ -58,7 +58,7 @@ StaticEventGroup_t wfxEventGroup; EventGroupHandle_t sl_wfx_event_group; TaskHandle_t wfx_events_task_handle; -static sl_wfx_mac_address_t ap_mac; +static MacAddress ap_mac; static uint32_t sta_ip; static wfx_wifi_scan_result_t ap_info; @@ -92,9 +92,6 @@ static wfx_wifi_scan_result_t ap_info; #define STA_IP_FAIL (0) #define WLAN_TASK_PRIORITY (1) -/***************************************************************************** - * macros - ******************************************************************************/ #define WE_ST_STARTED 1 #define WE_ST_STA_CONN 2 #define WE_ST_HW_STARTED 4 @@ -295,6 +292,19 @@ sl_status_t get_all_counters(void) } // namespace +CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, MutableByteSpan & address) +{ + VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); + +#ifdef SL_WFX_CONFIG_SOFTAP + chip::ByteSpan byteSpan((interface == SL_WFX_SOFTAP_INTERFACE) ? wifiContext.mac_addr_1.octet : wifiContext.mac_addr_0.octet); +#else + chip::ByteSpan byteSpan(wifiContext.mac_addr_0.octet); +#endif + + return CopySpanToMutableSpan(byteSpan, address); +} + /*************************************************************************** * @brief * Creates WFX events processing task. @@ -326,7 +336,7 @@ extern "C" sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * even /******** INDICATION ********/ case SL_WFX_STARTUP_IND_ID: { ChipLogProgress(DeviceLayer, "startup completed."); - HandleWFXSystemEvent(WIFI_EVENT, event_payload); + HandleWFXSystemEvent(event_payload); break; } case SL_WFX_CONNECT_IND_ID: { @@ -480,7 +490,7 @@ static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_res } ap->scan.chan = scan_result->channel; ap->scan.rssi = scan_result->rcpi; - memcpy(&ap->scan.bssid[0], &scan_result->mac[0], BSSID_LEN); + memcpy(&ap->scan.bssid[0], &scan_result->mac[0], kWifiMacAddressLength); scan_count++; } } @@ -515,7 +525,7 @@ static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication { case WFM_STATUS_SUCCESS: { ChipLogProgress(DeviceLayer, "STA-Connected"); - memcpy(&ap_mac.octet[0], mac, MAC_ADDRESS_FIRST_OCTET); + memcpy(ap_mac.data(), mac, kWifiMacAddressLength); sl_wfx_context->state = static_cast(static_cast(sl_wfx_context->state) | static_cast(SL_WFX_STA_INTERFACE_CONNECTED)); xEventGroupSetBits(sl_wfx_event_group, SL_WFX_CONNECT); @@ -692,23 +702,23 @@ static void wfx_events_task(void * p_arg) if (!hasNotifiedWifiConnectivity) { ChipLogProgress(DeviceLayer, "will notify WiFi connectivity"); - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac); + NotifyConnection(ap_mac); hasNotifiedWifiConnectivity = true; } } else if (dhcp_state == DHCP_OFF) { - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; } #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6) { - wfx_ipv6_notify(1); + NotifyIPv6Change(true); hasNotifiedIPV6 = true; if (!hasNotifiedWifiConnectivity) { - wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac); + NotifyConnection(ap_mac); hasNotifiedWifiConnectivity = true; } } @@ -719,10 +729,10 @@ static void wfx_events_task(void * p_arg) if (flags & SL_WFX_CONNECT) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; ChipLogProgress(DeviceLayer, "connected to AP"); @@ -744,10 +754,10 @@ static void wfx_events_task(void * p_arg) { #if (CHIP_DEVICE_CONFIG_ENABLE_IPV4) - wfx_ip_changed_notify(IP_STATUS_FAIL); + NotifyIPv4Change(false); hasNotifiedIPV4 = false; #endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4 - wfx_ipv6_notify(GET_IPV6_FAIL); + NotifyIPv6Change(false); hasNotifiedIPV6 = false; hasNotifiedWifiConnectivity = false; wifi_extra &= ~WE_ST_STA_CONN; @@ -1078,27 +1088,6 @@ sl_status_t wfx_connect_to_ap(void) return result; } -/**************************************************************************** - * @brief - * get the wifi mac addresss - * @param[in] interface: - * @param[in] addr : address - *****************************************************************************/ -void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr) -{ - sl_wfx_mac_address_t * mac; - -#ifdef SL_WFX_CONFIG_SOFTAP - mac = (interface == SL_WFX_SOFTAP_INTERFACE) ? &wifiContext.mac_addr_1 : &wifiContext.mac_addr_0; -#else - mac = &wifiContext.mac_addr_0; -#endif - *addr = *mac; - ChipLogDetail(DeviceLayer, "WLAN:Get WiFi Mac addr %02x:%02x:%02x:%02x:%02x:%02x", mac->octet[0], mac->octet[1], mac->octet[2], - mac->octet[3], mac->octet[4], mac->octet[5]); - memcpy(&ap_info.bssid[0], &mac->octet[0], 6); -} - /**************************************************************************** * @brief * function called when driver have ipv4 address @@ -1217,7 +1206,7 @@ void wfx_dhcp_got_ipv4(uint32_t ip) ChipLogDetail(DeviceLayer, "DHCP IP=%d.%d.%d.%d", ip4_addr[0], ip4_addr[1], ip4_addr[2], ip4_addr[3]); sta_ip = ip; - wfx_ip_changed_notify(IP_STATUS_SUCCESS); + NotifyIPv4Change(true); } #endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ diff --git a/src/platform/silabs/wifi/wfx_msgs.h b/src/platform/silabs/wifi/wfx_msgs.h index ec1744c998..5cef9a38ac 100644 --- a/src/platform/silabs/wifi/wfx_msgs.h +++ b/src/platform/silabs/wifi/wfx_msgs.h @@ -27,18 +27,6 @@ #include "sl_wfx_constants.h" #else -// These names exists in the Si SDK as typedef enum. If they are present in the WF200 builds, we end up with conflicting -// definitions but no erros because one is a define the other is a typedef enum. This causes different files to use different -// values. -#define SL_WFX_STARTUP_IND_ID (1) -#define SL_WFX_CONNECT_IND_ID (2) -#define SL_WFX_DISCONNECT_IND_ID (3) -#define SL_WFX_SCAN_COMPLETE_ID (4) - -typedef struct -{ - uint8_t octet[6]; ///< Table to store a MAC address -} sl_wfx_mac_address_t; /** * @brief General Message header structure * diff --git a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp index 2266989b90..f0b8634198 100644 --- a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp +++ b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.cpp @@ -18,6 +18,8 @@ #include #include +extern WfxRsi_t wfx_rsi; + namespace { // Thread for the WLAN RSI @@ -35,6 +37,19 @@ constexpr osThreadAttr_t kWlanTaskAttr = { .name = "wlan_rsi", } // namespace +CHIP_ERROR GetMacAddress(sl_wfx_interface_t interface, chip::MutableByteSpan & address) +{ + VerifyOrReturnError(address.size() >= kWifiMacAddressLength, CHIP_ERROR_BUFFER_TOO_SMALL); + +#ifdef SL_WFX_CONFIG_SOFTAP + chip::ByteSpan byteSpan((interface == SL_WFX_SOFTAP_INTERFACE) ? wfx_rsi.softap_mac : wfx_rsi.sta_mac); +#else + chip::ByteSpan byteSpan(wfx_rsi.sta_mac); +#endif + + return CopySpanToMutableSpan(byteSpan, address); +} + /********************************************************************* * @fn sl_status_t wfx_wifi_start(void) * @brief @@ -82,25 +97,6 @@ bool wfx_is_sta_mode_enabled(void) return wfx_rsi.dev_state.Has(WifiState::kStationMode); } -/********************************************************************* - * @fn void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t *addr) - * @brief - * get the wifi mac address - * @param[in] Interface: - * @param[in] addr : address - * @return - * None - ***********************************************************************/ -void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr) -{ - VerifyOrReturn(addr != nullptr); -#ifdef SL_WFX_CONFIG_SOFTAP - *addr = (interface == SL_WFX_SOFTAP_INTERFACE) ? wfx_rsi.softap_mac : wfx_rsi.sta_mac; -#else - *addr = wfx_rsi.sta_mac; -#endif -} - /********************************************************************* * @fn void wfx_set_wifi_provision(wfx_wifi_provision_t *cfg) * @brief @@ -160,7 +156,7 @@ sl_status_t wfx_connect_to_ap(void) VerifyOrReturnError(wfx_rsi.sec.ssid_length <= WFX_MAX_SSID_LENGTH, SL_STATUS_HAS_OVERFLOWED); ChipLogProgress(DeviceLayer, "connect to access point: %s", wfx_rsi.sec.ssid); - WifiEvent event = WifiEvent::kStationStartJoin; + WifiPlatformEvent event = WifiPlatformEvent::kStationStartJoin; sl_matter_wifi_post_event(event); return SL_STATUS_OK; } @@ -327,7 +323,7 @@ bool wfx_start_scan(char * ssid, void (*callback)(wfx_wifi_scan_result_t *)) VerifyOrReturnError(wfx_rsi.scan_ssid != nullptr, false); chip::Platform::CopyString(wfx_rsi.scan_ssid, wfx_rsi.scan_ssid_length, ssid); - WifiEvent event = WifiEvent::kScan; + WifiPlatformEvent event = WifiPlatformEvent::kScan; sl_matter_wifi_post_event(event); return true; diff --git a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h index 9073a02ef6..5ae23966f5 100644 --- a/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h +++ b/src/platform/silabs/wifi/wiseconnect-abstraction/WiseconnectInterfaceAbstraction.h @@ -22,16 +22,22 @@ #include #define WFX_RSI_DHCP_POLL_INTERVAL (250) /* Poll interval in ms for DHCP */ -#define GET_IPV6_SUCCESS (1) -extern WfxRsi_t wfx_rsi; +enum class WifiPlatformEvent : uint8_t +{ + kStationConnect = 0, + kStationDisconnect = 1, + kAPStart = 2, + kAPStop = 3, + kScan = 4, /* This combines the scan start and scan result events */ + kStationStartJoin = 5, + kStationDoDhcp = 6, + kStationDhcpDone = 7, + kStationDhcpPoll = 8, +}; void sl_matter_wifi_task(void * arg); -#if CHIP_DEVICE_CONFIG_ENABLE_IPV4 -void wfx_ip_changed_notify(int got_ip); -#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */ - int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap); int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info); int32_t wfx_rsi_reset_count(); @@ -44,4 +50,4 @@ sl_status_t sl_matter_wifi_platform_init(void); * * @param[in] event Event to process. */ -void sl_matter_wifi_post_event(WifiEvent event); +void sl_matter_wifi_post_event(WifiPlatformEvent event); From 38ad07d8742dd1a3106af68f6a612c6abedea5ca Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Wed, 4 Dec 2024 17:21:20 +0100 Subject: [PATCH 140/219] Allow to communicate with DUT via standard input (#36687) * Allow to communicate with DUT via standard input * Use fabric-sync-app.py stdin instead dedicated pipe * Drop pipe stdin forwarder in fabric-sync-app.py * Restyled by autopep8 * Wait for thread to stop * Fix referencing not-created variable --------- Co-authored-by: Restyled.io --- docs/testing/python.md | 5 ++ .../fabric-admin/scripts/fabric-sync-app.py | 37 +-------------- scripts/tests/run_python_test.py | 46 +++++++++++++++++-- src/python_testing/TC_BRBINFO_4_1.py | 3 +- src/python_testing/TC_CCTRL_2_1.py | 3 +- src/python_testing/TC_CCTRL_2_2.py | 3 +- src/python_testing/TC_CCTRL_2_3.py | 3 +- src/python_testing/TC_ECOINFO_2_1.py | 3 +- src/python_testing/TC_ECOINFO_2_2.py | 3 +- src/python_testing/TC_MCORE_FS_1_1.py | 3 +- src/python_testing/TC_MCORE_FS_1_2.py | 3 +- src/python_testing/TC_MCORE_FS_1_3.py | 13 +++--- src/python_testing/TC_MCORE_FS_1_4.py | 13 +++--- src/python_testing/TC_MCORE_FS_1_5.py | 3 +- .../chip/testing/metadata.py | 2 + 15 files changed, 82 insertions(+), 61 deletions(-) diff --git a/docs/testing/python.md b/docs/testing/python.md index a7bec6d07e..9bda585726 100644 --- a/docs/testing/python.md +++ b/docs/testing/python.md @@ -722,6 +722,11 @@ for that run, e.g.: - Example: `"Manual pairing code: \\[\\d+\\]"` +- `app-stdin-pipe`: Specifies the path to the named pipe that the test runner + might use to send input to the application. + + - Example: `/tmp/app-fifo` + - `script-args`: Specifies the arguments to be passed to the test script. - Example: diff --git a/examples/fabric-admin/scripts/fabric-sync-app.py b/examples/fabric-admin/scripts/fabric-sync-app.py index 3de85b9f67..a44a2a2d7a 100755 --- a/examples/fabric-admin/scripts/fabric-sync-app.py +++ b/examples/fabric-admin/scripts/fabric-sync-app.py @@ -16,7 +16,6 @@ import asyncio import contextlib -import os import shutil import signal import sys @@ -41,26 +40,6 @@ async def forward_f(prefix: bytes, f_in: asyncio.StreamReader, f_out.flush() -async def forward_pipe(pipe_path: str, f_out: asyncio.StreamWriter): - """Forward named pipe to f_out. - - Unfortunately, Python does not support async file I/O on named pipes. This - function performs busy waiting with a short asyncio-friendly sleep to read - from the pipe. - """ - fd = os.open(pipe_path, os.O_RDONLY | os.O_NONBLOCK) - while True: - try: - data = os.read(fd, 1024) - if data: - f_out.write(data) - await f_out.drain() - if not data: - await asyncio.sleep(0.1) - except BlockingIOError: - await asyncio.sleep(0.1) - - async def forward_stdin(f_out: asyncio.StreamWriter): """Forward stdin to f_out.""" loop = asyncio.get_event_loop() @@ -175,9 +154,6 @@ async def main(args): storage = TemporaryDirectory(prefix="fabric-sync-app") storage_dir = Path(storage.name) - if args.stdin_pipe and not args.stdin_pipe.exists(): - os.mkfifo(args.stdin_pipe) - admin, bridge = await asyncio.gather( run_admin( args.app_admin, @@ -206,8 +182,6 @@ def terminate(): admin.terminate() with contextlib.suppress(ProcessLookupError): bridge.terminate() - if args.stdin_pipe: - args.stdin_pipe.unlink(missing_ok=True) loop.remove_signal_handler(signal.SIGINT) loop.remove_signal_handler(signal.SIGTERM) @@ -249,17 +223,12 @@ def terminate(): await admin.send(f"pairing open-commissioning-window {bridge_node_id} {cw_endpoint_id}" f" {cw_option} {cw_timeout} {cw_iteration} {cw_discriminator}") - def get_input_forwarder(): - if args.stdin_pipe: - return forward_pipe(args.stdin_pipe, admin.p.stdin) - return forward_stdin(admin.p.stdin) - try: # Wait for any of the tasks to complete. _, pending = await asyncio.wait([ asyncio.create_task(admin.wait()), asyncio.create_task(bridge.wait()), - asyncio.create_task(get_input_forwarder()), + asyncio.create_task(forward_stdin(admin.p.stdin)), ], return_when=asyncio.FIRST_COMPLETED) # Cancel the remaining tasks. for task in pending: @@ -285,8 +254,6 @@ def get_input_forwarder(): help="fabric-admin RPC server port") parser.add_argument("--app-bridge-rpc-port", metavar="PORT", type=int, help="fabric-bridge RPC server port") - parser.add_argument("--stdin-pipe", metavar="PATH", type=Path, - help="read input from a named pipe instead of stdin") parser.add_argument("--storage-dir", metavar="PATH", type=Path, help=("directory to place storage files in; by default " "volatile storage is used")) @@ -309,7 +276,5 @@ def get_input_forwarder(): parser.error("fabric-admin executable not found in PATH. Use '--app-admin' argument to provide it.") if args.app_bridge is None or not args.app_bridge.exists(): parser.error("fabric-bridge-app executable not found in PATH. Use '--app-bridge' argument to provide it.") - if args.stdin_pipe and args.stdin_pipe.exists() and not args.stdin_pipe.is_fifo(): - parser.error("given stdin pipe exists and is not a named pipe") with contextlib.suppress(KeyboardInterrupt): asyncio.run(main(args)) diff --git a/scripts/tests/run_python_test.py b/scripts/tests/run_python_test.py index 0c40f9ac30..267fb51395 100755 --- a/scripts/tests/run_python_test.py +++ b/scripts/tests/run_python_test.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import contextlib import datetime import glob import io @@ -22,9 +23,12 @@ import os.path import pathlib import re +import select import shlex import sys +import threading import time +import typing import click import coloredlogs @@ -68,6 +72,23 @@ def process_test_script_output(line, is_stderr): return process_chip_output(line, is_stderr, TAG_PROCESS_TEST) +def forward_fifo(path: str, f_out: typing.BinaryIO, stop_event: threading.Event): + """Forward the content of a named pipe to a file-like object.""" + if not os.path.exists(path): + with contextlib.suppress(OSError): + os.mkfifo(path) + with open(os.open(path, os.O_RDONLY | os.O_NONBLOCK), 'rb') as f_in: + while not stop_event.is_set(): + if select.select([f_in], [], [], 0.5)[0]: + line = f_in.readline() + if not line: + break + f_out.write(line) + f_out.flush() + with contextlib.suppress(OSError): + os.unlink(path) + + @click.command() @click.option("--app", type=click.Path(exists=True), default=None, help='Path to local application to use, omit to use external apps.') @@ -79,6 +100,8 @@ def process_test_script_output(line, is_stderr): help='The extra arguments passed to the device. Can use placeholders like {SCRIPT_BASE_NAME}') @click.option("--app-ready-pattern", type=str, default=None, help='Delay test script start until given regular expression pattern is found in the application output.') +@click.option("--app-stdin-pipe", type=str, default=None, + help='Path for a standard input redirection named pipe to be used by the test script.') @click.option("--script", type=click.Path(exists=True), default=os.path.join(DEFAULT_CHIP_ROOT, 'src', 'controller', @@ -94,7 +117,8 @@ def process_test_script_output(line, is_stderr): help="Do not print output from passing tests. Use this flag in CI to keep GitHub log size manageable.") @click.option("--load-from-env", default=None, help="YAML file that contains values for environment variables.") def main(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: str, - app_ready_pattern: str, script: str, script_args: str, script_gdb: bool, quiet: bool, load_from_env): + app_ready_pattern: str, app_stdin_pipe: str, script: str, script_args: str, + script_gdb: bool, quiet: bool, load_from_env): if load_from_env: reader = MetadataReader(load_from_env) runs = reader.parse_script(script) @@ -106,6 +130,7 @@ def main(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: app=app, app_args=app_args, app_ready_pattern=app_ready_pattern, + app_stdin_pipe=app_stdin_pipe, script_args=script_args, script_gdb=script_gdb, ) @@ -128,11 +153,13 @@ def main(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: for run in runs: logging.info("Executing %s %s", run.py_script_path.split('/')[-1], run.run) main_impl(run.app, run.factory_reset, run.factory_reset_app_only, run.app_args or "", - run.app_ready_pattern, run.py_script_path, run.script_args or "", run.script_gdb, run.quiet) + run.app_ready_pattern, run.app_stdin_pipe, run.py_script_path, + run.script_args or "", run.script_gdb, run.quiet) def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_args: str, - app_ready_pattern: str, script: str, script_args: str, script_gdb: bool, quiet: bool): + app_ready_pattern: str, app_stdin_pipe: str, script: str, script_args: str, + script_gdb: bool, quiet: bool): app_args = app_args.replace('{SCRIPT_BASE_NAME}', os.path.splitext(os.path.basename(script))[0]) script_args = script_args.replace('{SCRIPT_BASE_NAME}', os.path.splitext(os.path.basename(script))[0]) @@ -154,6 +181,8 @@ def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_a pathlib.Path(match.group("path")).unlink(missing_ok=True) app_process = None + app_stdin_forwarding_thread = None + app_stdin_forwarding_stop_event = threading.Event() app_exit_code = 0 app_pid = 0 @@ -172,7 +201,13 @@ def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_a f_stdout=stream_output, f_stderr=stream_output) app_process.start(expected_output=app_ready_pattern, timeout=30) - app_process.p.stdin.close() + if app_stdin_pipe: + logging.info("Forwarding stdin from '%s' to app", app_stdin_pipe) + app_stdin_forwarding_thread = threading.Thread( + target=forward_fifo, args=(app_stdin_pipe, app_process.p.stdin, app_stdin_forwarding_stop_event)) + app_stdin_forwarding_thread.start() + else: + app_process.p.stdin.close() app_pid = app_process.p.pid script_command = [script, "--paa-trust-store-path", os.path.join(DEFAULT_CHIP_ROOT, MATTER_DEVELOPMENT_PAA_ROOT_CERTS), @@ -204,6 +239,9 @@ def main_impl(app: str, factory_reset: bool, factory_reset_app_only: bool, app_a if app_process: logging.info("Stopping app with SIGTERM") + if app_stdin_forwarding_thread: + app_stdin_forwarding_stop_event.set() + app_stdin_forwarding_thread.join() app_process.terminate() app_exit_code = app_process.returncode diff --git a/src/python_testing/TC_BRBINFO_4_1.py b/src/python_testing/TC_BRBINFO_4_1.py index 8c929d39b9..9caa513906 100644 --- a/src/python_testing/TC_BRBINFO_4_1.py +++ b/src/python_testing/TC_BRBINFO_4_1.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_CCTRL_2_1.py b/src/python_testing/TC_CCTRL_2_1.py index b656973f6a..24ebd19c52 100644 --- a/src/python_testing/TC_CCTRL_2_1.py +++ b/src/python_testing/TC_CCTRL_2_1.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_CCTRL_2_2.py b/src/python_testing/TC_CCTRL_2_2.py index 3f60fd9e38..01a4fc42cc 100644 --- a/src/python_testing/TC_CCTRL_2_2.py +++ b/src/python_testing/TC_CCTRL_2_2.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_CCTRL_2_3.py b/src/python_testing/TC_CCTRL_2_3.py index 83c25290cf..26a758bea0 100644 --- a/src/python_testing/TC_CCTRL_2_3.py +++ b/src/python_testing/TC_CCTRL_2_3.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_ECOINFO_2_1.py b/src/python_testing/TC_ECOINFO_2_1.py index a0adf75ac4..d86200d320 100644 --- a/src/python_testing/TC_ECOINFO_2_1.py +++ b/src/python_testing/TC_ECOINFO_2_1.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_ECOINFO_2_2.py b/src/python_testing/TC_ECOINFO_2_2.py index 6ce1e490d5..ce98a806ce 100644 --- a/src/python_testing/TC_ECOINFO_2_2.py +++ b/src/python_testing/TC_ECOINFO_2_2.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_MCORE_FS_1_1.py b/src/python_testing/TC_MCORE_FS_1_1.py index 780089b807..8428a99878 100755 --- a/src/python_testing/TC_MCORE_FS_1_1.py +++ b/src/python_testing/TC_MCORE_FS_1_1.py @@ -24,8 +24,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_MCORE_FS_1_2.py b/src/python_testing/TC_MCORE_FS_1_2.py index 97b5b87017..ffcbe006a3 100644 --- a/src/python_testing/TC_MCORE_FS_1_2.py +++ b/src/python_testing/TC_MCORE_FS_1_2.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/TC_MCORE_FS_1_3.py b/src/python_testing/TC_MCORE_FS_1_3.py index 4b732a1b3a..b4685f175d 100644 --- a/src/python_testing/TC_MCORE_FS_1_3.py +++ b/src/python_testing/TC_MCORE_FS_1_3.py @@ -26,8 +26,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json @@ -71,11 +72,11 @@ def setup_class(self): self.storage = None # Get the path to the TH_SERVER_NO_UID app from the user params. - th_server_app = self.user_params.get("th_server_no_uid_app_path", None) - if not th_server_app: + th_server_no_uid_app = self.user_params.get("th_server_no_uid_app_path", None) + if not th_server_no_uid_app: asserts.fail("This test requires a TH_SERVER_NO_UID app. Specify app path with --string-arg th_server_no_uid_app_path:") - if not os.path.exists(th_server_app): - asserts.fail(f"The path {th_server_app} does not exist") + if not os.path.exists(th_server_no_uid_app): + asserts.fail(f"The path {th_server_no_uid_app} does not exist") # Create a temporary storage directory for keeping KVS files. self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) @@ -94,7 +95,7 @@ def setup_class(self): # Start the TH_SERVER_NO_UID app. self.th_server = AppServerSubprocess( - th_server_app, + th_server_no_uid_app, storage_dir=self.storage.name, port=self.th_server_port, discriminator=self.th_server_discriminator, diff --git a/src/python_testing/TC_MCORE_FS_1_4.py b/src/python_testing/TC_MCORE_FS_1_4.py index c8f3e764d5..fb64378750 100644 --- a/src/python_testing/TC_MCORE_FS_1_4.py +++ b/src/python_testing/TC_MCORE_FS_1_4.py @@ -26,8 +26,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json @@ -129,11 +130,11 @@ def setup_class(self): asserts.fail(f"The path {th_fsa_bridge_path} does not exist") # Get the path to the TH_SERVER_NO_UID app from the user params. - th_server_app = self.user_params.get("th_server_no_uid_app_path", None) - if not th_server_app: + th_server_no_uid_app = self.user_params.get("th_server_no_uid_app_path", None) + if not th_server_no_uid_app: asserts.fail("This test requires a TH_SERVER_NO_UID app. Specify app path with --string-arg th_server_no_uid_app_path:") - if not os.path.exists(th_server_app): - asserts.fail(f"The path {th_server_app} does not exist") + if not os.path.exists(th_server_no_uid_app): + asserts.fail(f"The path {th_server_no_uid_app} does not exist") # Create a temporary storage directory for keeping KVS files. self.storage = tempfile.TemporaryDirectory(prefix=self.__class__.__name__) @@ -171,7 +172,7 @@ def setup_class(self): # Start the TH_SERVER_NO_UID app. self.th_server = AppServerSubprocess( - th_server_app, + th_server_no_uid_app, storage_dir=self.storage.name, port=self.th_server_port, discriminator=self.th_server_discriminator, diff --git a/src/python_testing/TC_MCORE_FS_1_5.py b/src/python_testing/TC_MCORE_FS_1_5.py index fc2eca6ee0..bd2f40a2ea 100755 --- a/src/python_testing/TC_MCORE_FS_1_5.py +++ b/src/python_testing/TC_MCORE_FS_1_5.py @@ -22,8 +22,9 @@ # test-runner-runs: # run1: # app: examples/fabric-admin/scripts/fabric-sync-app.py -# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --stdin-pipe=dut-fsa-stdin --discriminator=1234 +# app-args: --app-admin=${FABRIC_ADMIN_APP} --app-bridge=${FABRIC_BRIDGE_APP} --discriminator=1234 # app-ready-pattern: "Successfully opened pairing window on the device" +# app-stdin-pipe: dut-fsa-stdin # script-args: > # --PICS src/app/tests/suites/certification/ci-pics-values # --storage-path admin_storage.json diff --git a/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py index 2d40d792ac..3ec286dc77 100644 --- a/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py +++ b/src/python_testing/matter_testing_infrastructure/chip/testing/metadata.py @@ -27,6 +27,7 @@ class Metadata: app: str = "" app_args: Optional[str] = None app_ready_pattern: Optional[str] = None + app_stdin_pipe: Optional[str] = None script_args: Optional[str] = None factory_reset: bool = False factory_reset_app_only: bool = False @@ -148,6 +149,7 @@ def parse_script(self, py_script_path: str) -> List[Metadata]: app=attr.get("app", ""), app_args=attr.get("app-args"), app_ready_pattern=attr.get("app-ready-pattern"), + app_stdin_pipe=attr.get("app-stdin-pipe"), script_args=attr.get("script-args"), factory_reset=attr.get("factory-reset", False), quiet=attr.get("quiet", True), From 71dc879501d0000fa9eadf734e8d1644871f104b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 4 Dec 2024 15:44:10 -0500 Subject: [PATCH 141/219] Update Darwin availability annotations. (#36721) --- src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h | 4 ++-- src/darwin/Framework/CHIP/MTRDevice.h | 6 +++--- .../Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h index 98ee86a800..d1f40910f5 100644 --- a/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h +++ b/src/darwin/Framework/CHIP/MTRAttributeValueWaiter.h @@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN -MTR_NEWLY_AVAILABLE +MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)) @interface MTRAttributeValueWaiter : NSObject - (instancetype)init NS_UNAVAILABLE; + (instancetype)new NS_UNAVAILABLE; @@ -31,7 +31,7 @@ MTR_NEWLY_AVAILABLE */ - (void)cancel; -@property (readonly, nonatomic) NSUUID * UUID; +@property (readonly, nonatomic) NSUUID * UUID MTR_NEWLY_AVAILABLE; @end diff --git a/src/darwin/Framework/CHIP/MTRDevice.h b/src/darwin/Framework/CHIP/MTRDevice.h index 247223cbe4..b1ca179df6 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.h +++ b/src/darwin/Framework/CHIP/MTRDevice.h @@ -114,14 +114,14 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) * * A non-nil value if the vendor identifier has been determined from the device, nil if unknown. */ -@property (nonatomic, readonly, nullable, copy) NSNumber * vendorID MTR_NEWLY_AVAILABLE; +@property (nonatomic, readonly, nullable, copy) NSNumber * vendorID MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); /** * The Product Identifier associated with the device. * * A non-nil value if the product identifier has been determined from the device, nil if unknown. */ -@property (nonatomic, readonly, nullable, copy) NSNumber * productID MTR_NEWLY_AVAILABLE; +@property (nonatomic, readonly, nullable, copy) NSNumber * productID MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); /** * Network commissioning features supported by the device. @@ -362,7 +362,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1)) - (MTRAttributeValueWaiter *)waitForAttributeValues:(NSDictionary *> *)values timeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue - completion:(void (^)(NSError * _Nullable error))completion MTR_NEWLY_AVAILABLE; + completion:(void (^)(NSError * _Nullable error))completion MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); @end diff --git a/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h index 6daec1bb9d..45d19185d9 100644 --- a/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h +++ b/src/darwin/Framework/CHIP/XPC Protocol/MTRXPCServerProtocol.h @@ -21,10 +21,10 @@ NS_ASSUME_NONNULL_BEGIN MTR_EXTERN NSString * const MTRDeviceControllerRegistrationNodeIDsKey MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)); MTR_EXTERN NSString * const MTRDeviceControllerRegistrationNodeIDKey MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)); MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerContextKey MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)); -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerNodeIDKey MTR_NEWLY_AVAILABLE; -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerIsRunningKey MTR_NEWLY_AVAILABLE; -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationDeviceInternalStateKey MTR_NEWLY_AVAILABLE; -MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerCompressedFabricIDKey MTR_NEWLY_AVAILABLE; +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerNodeIDKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerIsRunningKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationDeviceInternalStateKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); +MTR_EXTERN NSString * const MTRDeviceControllerRegistrationControllerCompressedFabricIDKey MTR_AVAILABLE(ios(18.3), macos(15.3), watchos(11.3), tvos(18.3)); MTR_AVAILABLE(ios(18.2), macos(15.2), watchos(11.2), tvos(18.2)) @protocol MTRXPCServerProtocol_MTRDevice From ca772d7565fe48e01fecbb16f7a8491229dcb864 Mon Sep 17 00:00:00 2001 From: joonhaengHeo <85541460+joonhaengHeo@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:07:30 +0100 Subject: [PATCH 142/219] [Android] Implement DiagnosticLog (#36591) * Implement Android DiagnosticLog * Update from comment * Restyled * Update DiagnosticLog UX (Download complete / failed) * Fix timeout issue * Fix java-controller build error * modify from comment * Add javadoc, test cases * kotlin code style * Fix from comment * Fix build error --- .github/workflows/java-tests.yaml | 11 + .../CHIPTool/app/src/main/AndroidManifest.xml | 9 + .../chip/chiptool/SelectActionFragment.kt | 5 + .../clusterclient/DiagnosticLogFragment.kt | 172 ++++++++++ .../res/layout/diagnostic_log_fragment.xml | 87 ++++++ .../res/layout/select_action_fragment.xml | 8 + .../app/src/main/res/values/strings.xml | 4 + .../app/src/main/res/xml/file_paths.xml | 4 + examples/java-matter-controller/BUILD.gn | 2 + .../java/src/com/matter/controller/Main.kt | 12 + .../commands/bdx/DownloadLogCommand.kt | 73 +++++ .../PairOnNetworkLongDownloadLogCommand.kt | 96 ++++++ kotlin-detect-config.yaml | 1 + scripts/tests/java/bdx_test.py | 87 ++++++ scripts/tests/run_java_test.py | 42 +++ .../java/AndroidLogDownloadFromNode.cpp | 294 ++++++++++++++++++ .../java/AndroidLogDownloadFromNode.h | 95 ++++++ src/controller/java/BUILD.gn | 6 + .../java/BdxDiagnosticLogsReceiver.cpp | 121 +++++++ .../java/BdxDiagnosticLogsReceiver.h | 65 ++++ .../java/CHIPDeviceController-JNI.cpp | 23 ++ .../ChipDeviceController.java | 21 ++ .../devicecontroller/DiagnosticLogType.java | 52 ++++ .../devicecontroller/DownloadLogCallback.java | 49 +++ src/protocols/bdx/BdxUri.h | 2 + 25 files changed, 1341 insertions(+) create mode 100644 examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt create mode 100644 examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml create mode 100644 examples/android/CHIPTool/app/src/main/res/xml/file_paths.xml create mode 100644 examples/java-matter-controller/java/src/com/matter/controller/commands/bdx/DownloadLogCommand.kt create mode 100644 examples/java-matter-controller/java/src/com/matter/controller/commands/bdx/PairOnNetworkLongDownloadLogCommand.kt create mode 100755 scripts/tests/java/bdx_test.py create mode 100644 src/controller/java/AndroidLogDownloadFromNode.cpp create mode 100644 src/controller/java/AndroidLogDownloadFromNode.h create mode 100644 src/controller/java/BdxDiagnosticLogsReceiver.cpp create mode 100644 src/controller/java/BdxDiagnosticLogsReceiver.h create mode 100644 src/controller/java/src/chip/devicecontroller/DiagnosticLogType.java create mode 100644 src/controller/java/src/chip/devicecontroller/DownloadLogCallback.java diff --git a/.github/workflows/java-tests.yaml b/.github/workflows/java-tests.yaml index 504cb865a9..473cd48235 100644 --- a/.github/workflows/java-tests.yaml +++ b/.github/workflows/java-tests.yaml @@ -236,6 +236,17 @@ jobs: --tool-args "onnetwork-long --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 1000" \ --factoryreset \ ' + - name: Run Pairing Onnetwork and get diagnostic log Test + run: | + scripts/run_in_python_env.sh out/venv \ + './scripts/tests/run_java_test.py \ + --app out/linux-x64-all-clusters-ipv6only-no-ble-no-wifi-tsan-clang-test/chip-all-clusters-app \ + --app-args "--discriminator 3840 --interface-id -1 --crash_log ./crashLog.log --end_user_support_log ./enduser.log --network_diagnostics_log ./network.log" \ + --tool-path out/linux-x64-java-matter-controller \ + --tool-cluster "bdx" \ + --tool-args "onnetwork-long-downloadLog --nodeid 1 --setup-pin-code 20202021 --discriminator 3840 -t 3000 --logType CrashLogs --fileName ./crashLog.log" \ + --factoryreset \ + ' - name: Run Pairing Onnetwork Test run: | scripts/run_in_python_env.sh out/venv \ diff --git a/examples/android/CHIPTool/app/src/main/AndroidManifest.xml b/examples/android/CHIPTool/app/src/main/AndroidManifest.xml index 0526dc5a78..efd089817e 100644 --- a/examples/android/CHIPTool/app/src/main/AndroidManifest.xml +++ b/examples/android/CHIPTool/app/src/main/AndroidManifest.xml @@ -46,6 +46,15 @@ + + + diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt index 69bfdc1099..fb8141e72d 100644 --- a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/SelectActionFragment.kt @@ -72,6 +72,7 @@ class SelectActionFragment : Fragment() { binding.provisionCustomFlowBtn.setOnClickListener { handleProvisionCustomFlowClicked() } binding.wildcardBtn.setOnClickListener { handleWildcardClicked() } binding.unpairDeviceBtn.setOnClickListener { handleUnpairDeviceClicked() } + binding.diagnosticLogBtn.setOnClickListener { handleDiagnosticLogClicked() } binding.groupSettingBtn.setOnClickListener { handleGroupSettingClicked() } binding.otaProviderBtn.setOnClickListener { handleOTAProviderClicked() } binding.icdBtn.setOnClickListener { handleICDClicked() } @@ -225,6 +226,10 @@ class SelectActionFragment : Fragment() { showFragment(OtaProviderClientFragment.newInstance()) } + private fun handleDiagnosticLogClicked() { + showFragment(DiagnosticLogFragment.newInstance()) + } + /** Notifies listener of provision-WiFi-credentials button click. */ private fun handleProvisionWiFiCredentialsClicked() { getCallback()?.setNetworkType(ProvisionNetworkType.WIFI) diff --git a/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt new file mode 100644 index 0000000000..ea7d5438d2 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/java/com/google/chip/chiptool/clusterclient/DiagnosticLogFragment.kt @@ -0,0 +1,172 @@ +package com.google.chip.chiptool.clusterclient + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.os.Environment +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import androidx.core.content.FileProvider +import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope +import chip.devicecontroller.ChipDeviceController +import chip.devicecontroller.DiagnosticLogType +import chip.devicecontroller.DownloadLogCallback +import com.google.chip.chiptool.ChipClient +import com.google.chip.chiptool.R +import com.google.chip.chiptool.databinding.DiagnosticLogFragmentBinding +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +class DiagnosticLogFragment : Fragment() { + private val deviceController: ChipDeviceController + get() = ChipClient.getDeviceController(requireContext()) + + private lateinit var scope: CoroutineScope + + private lateinit var addressUpdateFragment: AddressUpdateFragment + + private var _binding: DiagnosticLogFragmentBinding? = null + private val binding + get() = _binding!! + + private val timeout: Long + get() = binding.timeoutEd.text.toString().toULongOrNull()?.toLong() ?: 0L + + private val diagnosticLogTypeList = DiagnosticLogType.values() + private val diagnosticLogType: DiagnosticLogType + get() = diagnosticLogTypeList[binding.diagnosticTypeSp.selectedItemPosition] + + private var mDownloadFile: File? = null + private var mDownloadFileOutputStream: FileOutputStream? = null + + private var mReceiveFileLen = 0U + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = DiagnosticLogFragmentBinding.inflate(inflater, container, false) + scope = viewLifecycleOwner.lifecycleScope + + addressUpdateFragment = + childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment + + binding.getDiagnosticLogBtn.setOnClickListener { scope.launch { getDiagnosticLogClick() } } + + binding.diagnosticTypeSp.adapter = + ArrayAdapter( + requireContext(), + android.R.layout.simple_spinner_dropdown_item, + diagnosticLogTypeList + ) + + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + inner class ChipDownloadLogCallback : DownloadLogCallback { + override fun onError(fabricIndex: Int, nodeId: Long, errorCode: Long) { + Log.d(TAG, "onError: $fabricIndex, ${nodeId.toULong()}, $errorCode") + showMessage("Downloading Failed") + mDownloadFileOutputStream?.flush() ?: return + } + + override fun onSuccess(fabricIndex: Int, nodeId: Long) { + Log.d(TAG, "onSuccess: $fabricIndex, ${nodeId.toULong()}") + mDownloadFileOutputStream?.flush() ?: return + showMessage("Downloading Completed") + mDownloadFile?.let { showNotification(it) } ?: return + } + + override fun onTransferData(fabricIndex: Int, nodeId: Long, data: ByteArray): Boolean { + Log.d(TAG, "onTransferData : ${data.size}") + if (mDownloadFileOutputStream == null) { + Log.d(TAG, "mDownloadFileOutputStream or mDownloadFile is null") + return false + } + return addData(mDownloadFileOutputStream!!, data) + } + + private fun addData(outputStream: FileOutputStream, data: ByteArray): Boolean { + try { + outputStream.write(data) + } catch (e: IOException) { + Log.d(TAG, "IOException", e) + return false + } + mReceiveFileLen += data.size.toUInt() + showMessage("Receive Data Size : $mReceiveFileLen") + return true + } + } + + private fun getDiagnosticLogClick() { + mDownloadFile = + createLogFile( + deviceController.fabricIndex.toUInt(), + addressUpdateFragment.deviceId.toULong(), + diagnosticLogType + ) + mDownloadFileOutputStream = FileOutputStream(mDownloadFile) + deviceController.downloadLogFromNode( + addressUpdateFragment.deviceId, + diagnosticLogType, + timeout, + ChipDownloadLogCallback() + ) + } + + private fun isExternalStorageWritable(): Boolean { + return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED + } + + private fun createLogFile(fabricIndex: UInt, nodeId: ULong, type: DiagnosticLogType): File? { + if (!isExternalStorageWritable()) { + return null + } + val now = System.currentTimeMillis() + val fileName = "${type}_${fabricIndex}_${nodeId}_$now.txt" + mReceiveFileLen = 0U + return File(requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), fileName) + } + + private fun showNotification(file: File) { + val intent = + Intent(Intent.ACTION_VIEW).apply { + setDataAndType(getFileUri(file), "text/plain") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + } + + requireActivity().startActivity(intent) + } + + private fun getFileUri(file: File): Uri { + return FileProvider.getUriForFile( + requireContext(), + "${requireContext().packageName}.provider", + file + ) + } + + private fun showMessage(msg: String) { + requireActivity().runOnUiThread { binding.diagnosticLogTv.text = msg } + } + + companion object { + private const val TAG = "DiagnosticLogFragment" + + fun newInstance(): DiagnosticLogFragment = DiagnosticLogFragment() + } +} diff --git a/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml b/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml new file mode 100644 index 0000000000..56b770a645 --- /dev/null +++ b/examples/android/CHIPTool/app/src/main/res/layout/diagnostic_log_fragment.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + +