/*
 *
 *    Copyright (c) 2022 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.
 */

// THIS FILE IS GENERATED BY ZAP

#pragma once

#import <Matter/Matter.h>

#include <cstdint>
#include <string>
#include <type_traits>

#include <app-common/zap-generated/cluster-objects.h>
#include <app/data-model/DecodableList.h>
#include <commands/clusters/ClusterCommandBridge.h>
#include <commands/clusters/ComplexArgument.h>
#include <commands/clusters/ReportCommandBridge.h>
#include <commands/clusters/WriteAttributeCommandBridge.h>

/*----------------------------------------------------------------------------*\
| Cluster Name                                                        |   ID   |
|---------------------------------------------------------------------+--------|
| Identify                                                            | 0x0003 |
| Groups                                                              | 0x0004 |
| Scenes                                                              | 0x0005 |
| OnOff                                                               | 0x0006 |
| OnOffSwitchConfiguration                                            | 0x0007 |
| LevelControl                                                        | 0x0008 |
| BinaryInputBasic                                                    | 0x000F |
| PulseWidthModulation                                                | 0x001C |
| Descriptor                                                          | 0x001D |
| Binding                                                             | 0x001E |
| AccessControl                                                       | 0x001F |
| Actions                                                             | 0x0025 |
| Basic                                                               | 0x0028 |
| OtaSoftwareUpdateProvider                                           | 0x0029 |
| OtaSoftwareUpdateRequestor                                          | 0x002A |
| LocalizationConfiguration                                           | 0x002B |
| TimeFormatLocalization                                              | 0x002C |
| UnitLocalization                                                    | 0x002D |
| PowerSourceConfiguration                                            | 0x002E |
| PowerSource                                                         | 0x002F |
| GeneralCommissioning                                                | 0x0030 |
| NetworkCommissioning                                                | 0x0031 |
| DiagnosticLogs                                                      | 0x0032 |
| GeneralDiagnostics                                                  | 0x0033 |
| SoftwareDiagnostics                                                 | 0x0034 |
| ThreadNetworkDiagnostics                                            | 0x0035 |
| WiFiNetworkDiagnostics                                              | 0x0036 |
| EthernetNetworkDiagnostics                                          | 0x0037 |
| TimeSynchronization                                                 | 0x0038 |
| BridgedDeviceBasic                                                  | 0x0039 |
| Switch                                                              | 0x003B |
| AdministratorCommissioning                                          | 0x003C |
| OperationalCredentials                                              | 0x003E |
| GroupKeyManagement                                                  | 0x003F |
| FixedLabel                                                          | 0x0040 |
| UserLabel                                                           | 0x0041 |
| ProxyConfiguration                                                  | 0x0042 |
| ProxyDiscovery                                                      | 0x0043 |
| ProxyValid                                                          | 0x0044 |
| BooleanState                                                        | 0x0045 |
| ModeSelect                                                          | 0x0050 |
| DoorLock                                                            | 0x0101 |
| WindowCovering                                                      | 0x0102 |
| BarrierControl                                                      | 0x0103 |
| PumpConfigurationAndControl                                         | 0x0200 |
| Thermostat                                                          | 0x0201 |
| FanControl                                                          | 0x0202 |
| ThermostatUserInterfaceConfiguration                                | 0x0204 |
| ColorControl                                                        | 0x0300 |
| BallastConfiguration                                                | 0x0301 |
| IlluminanceMeasurement                                              | 0x0400 |
| TemperatureMeasurement                                              | 0x0402 |
| PressureMeasurement                                                 | 0x0403 |
| FlowMeasurement                                                     | 0x0404 |
| RelativeHumidityMeasurement                                         | 0x0405 |
| OccupancySensing                                                    | 0x0406 |
| WakeOnLan                                                           | 0x0503 |
| Channel                                                             | 0x0504 |
| TargetNavigator                                                     | 0x0505 |
| MediaPlayback                                                       | 0x0506 |
| MediaInput                                                          | 0x0507 |
| LowPower                                                            | 0x0508 |
| KeypadInput                                                         | 0x0509 |
| ContentLauncher                                                     | 0x050A |
| AudioOutput                                                         | 0x050B |
| ApplicationLauncher                                                 | 0x050C |
| ApplicationBasic                                                    | 0x050D |
| AccountLogin                                                        | 0x050E |
| ElectricalMeasurement                                               | 0x0B04 |
| TestCluster                                                         | 0xFFF1FC05|
| FaultInjection                                                      | 0xFFF1FC06|
\*----------------------------------------------------------------------------*/

/*----------------------------------------------------------------------------*\
| Cluster Identify                                                    | 0x0003 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Identify                                                          |   0x00 |
| * TriggerEffect                                                     |   0x40 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * IdentifyTime                                                      | 0x0000 |
| * IdentifyType                                                      | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command Identify
 */
class IdentifyIdentify : public ClusterCommand {
public:
    IdentifyIdentify()
        : ClusterCommand("identify")
    {
        AddArgument("IdentifyTime", 0, UINT16_MAX, &mRequest.identifyTime);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRIdentifyClusterIdentifyParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.identifyTime = [NSNumber numberWithUnsignedShort:mRequest.identifyTime];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster identifyWithParams:params
                             completion:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Identify::Commands::Identify::Type mRequest;
};

/*
 * Command TriggerEffect
 */
class IdentifyTriggerEffect : public ClusterCommand {
public:
    IdentifyTriggerEffect()
        : ClusterCommand("trigger-effect")
    {
        AddArgument("EffectIdentifier", 0, UINT8_MAX, &mRequest.effectIdentifier);
        AddArgument("EffectVariant", 0, UINT8_MAX, &mRequest.effectVariant);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) command (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRIdentifyClusterTriggerEffectParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.effectIdentifier = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.effectIdentifier)];
        params.effectVariant = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.effectVariant)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster triggerEffectWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Identify::Commands::TriggerEffect::Type mRequest;
};

/*
 * Attribute IdentifyTime
 */
class ReadIdentifyIdentifyTime : public ReadAttribute {
public:
    ReadIdentifyIdentifyTime()
        : ReadAttribute("identify-time")
    {
    }

    ~ReadIdentifyIdentifyTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeIdentifyTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.IdentifyTime response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify IdentifyTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteIdentifyIdentifyTime : public WriteAttribute {
public:
    WriteIdentifyIdentifyTime()
        : WriteAttribute("identify-time")
    {
        AddArgument("attr-name", "identify-time");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteIdentifyIdentifyTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeIdentifyTimeWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("Identify IdentifyTime write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeIdentifyIdentifyTime : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyIdentifyTime()
        : SubscribeAttribute("identify-time")
    {
    }

    ~SubscribeAttributeIdentifyIdentifyTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeIdentifyTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.IdentifyTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute IdentifyType
 */
class ReadIdentifyIdentifyType : public ReadAttribute {
public:
    ReadIdentifyIdentifyType()
        : ReadAttribute("identify-type")
    {
    }

    ~ReadIdentifyIdentifyType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeIdentifyTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.IdentifyType response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify IdentifyType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIdentifyIdentifyType : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyIdentifyType()
        : SubscribeAttribute("identify-type")
    {
    }

    ~SubscribeAttributeIdentifyIdentifyType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeIdentifyTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.IdentifyType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadIdentifyGeneratedCommandList : public ReadAttribute {
public:
    ReadIdentifyGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadIdentifyGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIdentifyGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeIdentifyGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadIdentifyAcceptedCommandList : public ReadAttribute {
public:
    ReadIdentifyAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadIdentifyAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIdentifyAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeIdentifyAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadIdentifyAttributeList : public ReadAttribute {
public:
    ReadIdentifyAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadIdentifyAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIdentifyAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeIdentifyAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadIdentifyFeatureMap : public ReadAttribute {
public:
    ReadIdentifyFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadIdentifyFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIdentifyFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeIdentifyFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadIdentifyClusterRevision : public ReadAttribute {
public:
    ReadIdentifyClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadIdentifyClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Identify.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Identify ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIdentifyClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeIdentifyClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeIdentifyClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000003) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIdentify * cluster = [[MTRBaseClusterIdentify alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Identify.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Groups                                                      | 0x0004 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * AddGroup                                                          |   0x00 |
| * ViewGroup                                                         |   0x01 |
| * GetGroupMembership                                                |   0x02 |
| * RemoveGroup                                                       |   0x03 |
| * RemoveAllGroups                                                   |   0x04 |
| * AddGroupIfIdentifying                                             |   0x05 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NameSupport                                                       | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command AddGroup
 */
class GroupsAddGroup : public ClusterCommand {
public:
    GroupsAddGroup()
        : ClusterCommand("add-group")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("GroupName", &mRequest.groupName);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRGroupsClusterAddGroupParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.groupName = [[NSString alloc] initWithBytes:mRequest.groupName.data()
                                                    length:mRequest.groupName.size()
                                                  encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster addGroupWithParams:params
                             completion:^(MTRGroupsClusterAddGroupResponseParams * _Nullable values, NSError * _Nullable error) {
                                 NSLog(@"Values: %@", values);
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Groups::Commands::AddGroup::Type mRequest;
};

/*
 * Command ViewGroup
 */
class GroupsViewGroup : public ClusterCommand {
public:
    GroupsViewGroup()
        : ClusterCommand("view-group")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRGroupsClusterViewGroupParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster viewGroupWithParams:params
                              completion:^(MTRGroupsClusterViewGroupResponseParams * _Nullable values, NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Groups::Commands::ViewGroup::Type mRequest;
};

/*
 * Command GetGroupMembership
 */
class GroupsGetGroupMembership : public ClusterCommand {
public:
    GroupsGetGroupMembership()
        : ClusterCommand("get-group-membership")
        , mComplex_GroupList(&mRequest.groupList)
    {
        AddArgument("GroupList", &mComplex_GroupList);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRGroupsClusterGetGroupMembershipParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.groupList) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedShort:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.groupList = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getGroupMembershipWithParams:params
                                       completion:^(MTRGroupsClusterGetGroupMembershipResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Groups::Commands::GetGroupMembership::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::GroupId>> mComplex_GroupList;
};

/*
 * Command RemoveGroup
 */
class GroupsRemoveGroup : public ClusterCommand {
public:
    GroupsRemoveGroup()
        : ClusterCommand("remove-group")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRGroupsClusterRemoveGroupParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                removeGroupWithParams:params
                           completion:^(MTRGroupsClusterRemoveGroupResponseParams * _Nullable values, NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Groups::Commands::RemoveGroup::Type mRequest;
};

/*
 * Command RemoveAllGroups
 */
class GroupsRemoveAllGroups : public ClusterCommand {
public:
    GroupsRemoveAllGroups()
        : ClusterCommand("remove-all-groups")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRGroupsClusterRemoveAllGroupsParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster removeAllGroupsWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command AddGroupIfIdentifying
 */
class GroupsAddGroupIfIdentifying : public ClusterCommand {
public:
    GroupsAddGroupIfIdentifying()
        : ClusterCommand("add-group-if-identifying")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("GroupName", &mRequest.groupName);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRGroupsClusterAddGroupIfIdentifyingParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.groupName = [[NSString alloc] initWithBytes:mRequest.groupName.data()
                                                    length:mRequest.groupName.size()
                                                  encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster addGroupIfIdentifyingWithParams:params
                                          completion:^(NSError * _Nullable error) {
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Groups::Commands::AddGroupIfIdentifying::Type mRequest;
};

/*
 * Attribute NameSupport
 */
class ReadGroupsNameSupport : public ReadAttribute {
public:
    ReadGroupsNameSupport()
        : ReadAttribute("name-support")
    {
    }

    ~ReadGroupsNameSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeNameSupportWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Groups.NameSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("Groups NameSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupsNameSupport : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsNameSupport()
        : SubscribeAttribute("name-support")
    {
    }

    ~SubscribeAttributeGroupsNameSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNameSupportWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.NameSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGroupsGeneratedCommandList : public ReadAttribute {
public:
    ReadGroupsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGroupsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Groups.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Groups GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGroupsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGroupsAcceptedCommandList : public ReadAttribute {
public:
    ReadGroupsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGroupsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Groups.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Groups AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGroupsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGroupsAttributeList : public ReadAttribute {
public:
    ReadGroupsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGroupsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Groups.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Groups AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGroupsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGroupsFeatureMap : public ReadAttribute {
public:
    ReadGroupsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGroupsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Groups.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Groups FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGroupsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGroupsClusterRevision : public ReadAttribute {
public:
    ReadGroupsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGroupsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Groups.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Groups ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGroupsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGroupsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000004) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroups * cluster = [[MTRBaseClusterGroups alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Groups.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Scenes                                                      | 0x0005 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * AddScene                                                          |   0x00 |
| * ViewScene                                                         |   0x01 |
| * RemoveScene                                                       |   0x02 |
| * RemoveAllScenes                                                   |   0x03 |
| * StoreScene                                                        |   0x04 |
| * RecallScene                                                       |   0x05 |
| * GetSceneMembership                                                |   0x06 |
| * EnhancedAddScene                                                  |   0x40 |
| * EnhancedViewScene                                                 |   0x41 |
| * CopyScene                                                         |   0x42 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * SceneCount                                                        | 0x0000 |
| * CurrentScene                                                      | 0x0001 |
| * CurrentGroup                                                      | 0x0002 |
| * SceneValid                                                        | 0x0003 |
| * NameSupport                                                       | 0x0004 |
| * LastConfiguredBy                                                  | 0x0005 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command AddScene
 */
class ScenesAddScene : public ClusterCommand {
public:
    ScenesAddScene()
        : ClusterCommand("add-scene")
        , mComplex_ExtensionFieldSets(&mRequest.extensionFieldSets)
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("SceneName", &mRequest.sceneName);
        AddArgument("ExtensionFieldSets", &mComplex_ExtensionFieldSets);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterAddSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.sceneName = [[NSString alloc] initWithBytes:mRequest.sceneName.data()
                                                    length:mRequest.sceneName.size()
                                                  encoding:NSUTF8StringEncoding];
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.extensionFieldSets) {
                MTRScenesClusterExtensionFieldSet * newElement_0;
                newElement_0 = [MTRScenesClusterExtensionFieldSet new];
                newElement_0.clusterId = [NSNumber numberWithUnsignedInt:entry_0.clusterId];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.attributeValueList) {
                        MTRScenesClusterAttributeValuePair * newElement_2;
                        newElement_2 = [MTRScenesClusterAttributeValuePair new];
                        if (entry_2.attributeId.HasValue()) {
                            newElement_2.attributeId = [NSNumber numberWithUnsignedInt:entry_2.attributeId.Value()];
                        } else {
                            newElement_2.attributeId = nil;
                        }
                        { // Scope for our temporary variables
                            auto * array_4 = [NSMutableArray new];
                            for (auto & entry_4 : entry_2.attributeValue) {
                                NSNumber * newElement_4;
                                newElement_4 = [NSNumber numberWithUnsignedChar:entry_4];
                                [array_4 addObject:newElement_4];
                            }
                            newElement_2.attributeValue = array_4;
                        }
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.attributeValueList = array_2;
                }
                [array_0 addObject:newElement_0];
            }
            params.extensionFieldSets = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster addSceneWithParams:params
                             completion:^(MTRScenesClusterAddSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                                 NSLog(@"Values: %@", values);
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::AddScene::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::Scenes::Structs::ExtensionFieldSet::Type>>
        mComplex_ExtensionFieldSets;
};

/*
 * Command ViewScene
 */
class ScenesViewScene : public ClusterCommand {
public:
    ScenesViewScene()
        : ClusterCommand("view-scene")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterViewSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster viewSceneWithParams:params
                              completion:^(MTRScenesClusterViewSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::ViewScene::Type mRequest;
};

/*
 * Command RemoveScene
 */
class ScenesRemoveScene : public ClusterCommand {
public:
    ScenesRemoveScene()
        : ClusterCommand("remove-scene")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterRemoveSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                removeSceneWithParams:params
                           completion:^(MTRScenesClusterRemoveSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::RemoveScene::Type mRequest;
};

/*
 * Command RemoveAllScenes
 */
class ScenesRemoveAllScenes : public ClusterCommand {
public:
    ScenesRemoveAllScenes()
        : ClusterCommand("remove-all-scenes")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterRemoveAllScenesParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster removeAllScenesWithParams:params
                                    completion:^(MTRScenesClusterRemoveAllScenesResponseParams * _Nullable values,
                                        NSError * _Nullable error) {
                                        NSLog(@"Values: %@", values);
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::RemoveAllScenes::Type mRequest;
};

/*
 * Command StoreScene
 */
class ScenesStoreScene : public ClusterCommand {
public:
    ScenesStoreScene()
        : ClusterCommand("store-scene")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterStoreSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                storeSceneWithParams:params
                          completion:^(MTRScenesClusterStoreSceneResponseParams * _Nullable values, NSError * _Nullable error) {
                              NSLog(@"Values: %@", values);
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::StoreScene::Type mRequest;
};

/*
 * Command RecallScene
 */
class ScenesRecallScene : public ClusterCommand {
public:
    ScenesRecallScene()
        : ClusterCommand("recall-scene")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterRecallSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        if (mRequest.transitionTime.HasValue()) {
            if (mRequest.transitionTime.Value().IsNull()) {
                params.transitionTime = nil;
            } else {
                params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime.Value().Value()];
            }
        } else {
            params.transitionTime = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster recallSceneWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::RecallScene::Type mRequest;
};

/*
 * Command GetSceneMembership
 */
class ScenesGetSceneMembership : public ClusterCommand {
public:
    ScenesGetSceneMembership()
        : ClusterCommand("get-scene-membership")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterGetSceneMembershipParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getSceneMembershipWithParams:params
                                       completion:^(MTRScenesClusterGetSceneMembershipResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::GetSceneMembership::Type mRequest;
};

/*
 * Command EnhancedAddScene
 */
class ScenesEnhancedAddScene : public ClusterCommand {
public:
    ScenesEnhancedAddScene()
        : ClusterCommand("enhanced-add-scene")
        , mComplex_ExtensionFieldSets(&mRequest.extensionFieldSets)
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("SceneName", &mRequest.sceneName);
        AddArgument("ExtensionFieldSets", &mComplex_ExtensionFieldSets);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterEnhancedAddSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.sceneName = [[NSString alloc] initWithBytes:mRequest.sceneName.data()
                                                    length:mRequest.sceneName.size()
                                                  encoding:NSUTF8StringEncoding];
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.extensionFieldSets) {
                MTRScenesClusterExtensionFieldSet * newElement_0;
                newElement_0 = [MTRScenesClusterExtensionFieldSet new];
                newElement_0.clusterId = [NSNumber numberWithUnsignedInt:entry_0.clusterId];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.attributeValueList) {
                        MTRScenesClusterAttributeValuePair * newElement_2;
                        newElement_2 = [MTRScenesClusterAttributeValuePair new];
                        if (entry_2.attributeId.HasValue()) {
                            newElement_2.attributeId = [NSNumber numberWithUnsignedInt:entry_2.attributeId.Value()];
                        } else {
                            newElement_2.attributeId = nil;
                        }
                        { // Scope for our temporary variables
                            auto * array_4 = [NSMutableArray new];
                            for (auto & entry_4 : entry_2.attributeValue) {
                                NSNumber * newElement_4;
                                newElement_4 = [NSNumber numberWithUnsignedChar:entry_4];
                                [array_4 addObject:newElement_4];
                            }
                            newElement_2.attributeValue = array_4;
                        }
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.attributeValueList = array_2;
                }
                [array_0 addObject:newElement_0];
            }
            params.extensionFieldSets = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enhancedAddSceneWithParams:params
                                     completion:^(MTRScenesClusterEnhancedAddSceneResponseParams * _Nullable values,
                                         NSError * _Nullable error) {
                                         NSLog(@"Values: %@", values);
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::EnhancedAddScene::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::Scenes::Structs::ExtensionFieldSet::Type>>
        mComplex_ExtensionFieldSets;
};

/*
 * Command EnhancedViewScene
 */
class ScenesEnhancedViewScene : public ClusterCommand {
public:
    ScenesEnhancedViewScene()
        : ClusterCommand("enhanced-view-scene")
    {
        AddArgument("GroupId", 0, UINT16_MAX, &mRequest.groupId);
        AddArgument("SceneId", 0, UINT8_MAX, &mRequest.sceneId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000041) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterEnhancedViewSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupId = [NSNumber numberWithUnsignedShort:mRequest.groupId];
        params.sceneId = [NSNumber numberWithUnsignedChar:mRequest.sceneId];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enhancedViewSceneWithParams:params
                                      completion:^(MTRScenesClusterEnhancedViewSceneResponseParams * _Nullable values,
                                          NSError * _Nullable error) {
                                          NSLog(@"Values: %@", values);
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::EnhancedViewScene::Type mRequest;
};

/*
 * Command CopyScene
 */
class ScenesCopyScene : public ClusterCommand {
public:
    ScenesCopyScene()
        : ClusterCommand("copy-scene")
    {
        AddArgument("Mode", 0, UINT8_MAX, &mRequest.mode);
        AddArgument("GroupIdFrom", 0, UINT16_MAX, &mRequest.groupIdFrom);
        AddArgument("SceneIdFrom", 0, UINT8_MAX, &mRequest.sceneIdFrom);
        AddArgument("GroupIdTo", 0, UINT16_MAX, &mRequest.groupIdTo);
        AddArgument("SceneIdTo", 0, UINT8_MAX, &mRequest.sceneIdTo);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) command (0x00000042) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRScenesClusterCopySceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.mode = [NSNumber numberWithUnsignedChar:mRequest.mode.Raw()];
        params.groupIdFrom = [NSNumber numberWithUnsignedShort:mRequest.groupIdFrom];
        params.sceneIdFrom = [NSNumber numberWithUnsignedChar:mRequest.sceneIdFrom];
        params.groupIdTo = [NSNumber numberWithUnsignedShort:mRequest.groupIdTo];
        params.sceneIdTo = [NSNumber numberWithUnsignedChar:mRequest.sceneIdTo];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster copySceneWithParams:params
                              completion:^(MTRScenesClusterCopySceneResponseParams * _Nullable values, NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Scenes::Commands::CopyScene::Type mRequest;
};

/*
 * Attribute SceneCount
 */
class ReadScenesSceneCount : public ReadAttribute {
public:
    ReadScenesSceneCount()
        : ReadAttribute("scene-count")
    {
    }

    ~ReadScenesSceneCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeSceneCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.SceneCount response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes SceneCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesSceneCount : public SubscribeAttribute {
public:
    SubscribeAttributeScenesSceneCount()
        : SubscribeAttribute("scene-count")
    {
    }

    ~SubscribeAttributeScenesSceneCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSceneCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.SceneCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentScene
 */
class ReadScenesCurrentScene : public ReadAttribute {
public:
    ReadScenesCurrentScene()
        : ReadAttribute("current-scene")
    {
    }

    ~ReadScenesCurrentScene() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentSceneWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.CurrentScene response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes CurrentScene read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesCurrentScene : public SubscribeAttribute {
public:
    SubscribeAttributeScenesCurrentScene()
        : SubscribeAttribute("current-scene")
    {
    }

    ~SubscribeAttributeScenesCurrentScene() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentSceneWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.CurrentScene response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentGroup
 */
class ReadScenesCurrentGroup : public ReadAttribute {
public:
    ReadScenesCurrentGroup()
        : ReadAttribute("current-group")
    {
    }

    ~ReadScenesCurrentGroup() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentGroupWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.CurrentGroup response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes CurrentGroup read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesCurrentGroup : public SubscribeAttribute {
public:
    SubscribeAttributeScenesCurrentGroup()
        : SubscribeAttribute("current-group")
    {
    }

    ~SubscribeAttributeScenesCurrentGroup() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentGroupWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.CurrentGroup response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SceneValid
 */
class ReadScenesSceneValid : public ReadAttribute {
public:
    ReadScenesSceneValid()
        : ReadAttribute("scene-valid")
    {
    }

    ~ReadScenesSceneValid() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeSceneValidWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.SceneValid response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes SceneValid read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesSceneValid : public SubscribeAttribute {
public:
    SubscribeAttributeScenesSceneValid()
        : SubscribeAttribute("scene-valid")
    {
    }

    ~SubscribeAttributeScenesSceneValid() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSceneValidWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.SceneValid response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NameSupport
 */
class ReadScenesNameSupport : public ReadAttribute {
public:
    ReadScenesNameSupport()
        : ReadAttribute("name-support")
    {
    }

    ~ReadScenesNameSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeNameSupportWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.NameSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes NameSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesNameSupport : public SubscribeAttribute {
public:
    SubscribeAttributeScenesNameSupport()
        : SubscribeAttribute("name-support")
    {
    }

    ~SubscribeAttributeScenesNameSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNameSupportWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.NameSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastConfiguredBy
 */
class ReadScenesLastConfiguredBy : public ReadAttribute {
public:
    ReadScenesLastConfiguredBy()
        : ReadAttribute("last-configured-by")
    {
    }

    ~ReadScenesLastConfiguredBy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeLastConfiguredByWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.LastConfiguredBy response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes LastConfiguredBy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesLastConfiguredBy : public SubscribeAttribute {
public:
    SubscribeAttributeScenesLastConfiguredBy()
        : SubscribeAttribute("last-configured-by")
    {
    }

    ~SubscribeAttributeScenesLastConfiguredBy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLastConfiguredByWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.LastConfiguredBy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadScenesGeneratedCommandList : public ReadAttribute {
public:
    ReadScenesGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadScenesGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeScenesGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeScenesGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadScenesAcceptedCommandList : public ReadAttribute {
public:
    ReadScenesAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadScenesAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeScenesAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeScenesAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadScenesAttributeList : public ReadAttribute {
public:
    ReadScenesAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadScenesAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeScenesAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeScenesAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadScenesFeatureMap : public ReadAttribute {
public:
    ReadScenesFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadScenesFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeScenesFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeScenesFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadScenesClusterRevision : public ReadAttribute {
public:
    ReadScenesClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadScenesClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Scenes.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Scenes ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeScenesClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeScenesClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeScenesClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000005) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterScenes * cluster = [[MTRBaseClusterScenes alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Scenes.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OnOff                                                       | 0x0006 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Off                                                               |   0x00 |
| * On                                                                |   0x01 |
| * Toggle                                                            |   0x02 |
| * OffWithEffect                                                     |   0x40 |
| * OnWithRecallGlobalScene                                           |   0x41 |
| * OnWithTimedOff                                                    |   0x42 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * OnOff                                                             | 0x0000 |
| * GlobalSceneControl                                                | 0x4000 |
| * OnTime                                                            | 0x4001 |
| * OffWaitTime                                                       | 0x4002 |
| * StartUpOnOff                                                      | 0x4003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command Off
 */
class OnOffOff : public ClusterCommand {
public:
    OnOffOff()
        : ClusterCommand("off")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTROnOffClusterOffParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster offWithParams:params
                        completion:^(NSError * _Nullable error) {
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command On
 */
class OnOffOn : public ClusterCommand {
public:
    OnOffOn()
        : ClusterCommand("on")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTROnOffClusterOnParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster onWithParams:params
                       completion:^(NSError * _Nullable error) {
                           responsesNeeded--;
                           if (error != nil) {
                               mError = error;
                               LogNSError("Error", error);
                           }
                           if (responsesNeeded == 0) {
                               SetCommandExitStatus(mError);
                           }
                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Toggle
 */
class OnOffToggle : public ClusterCommand {
public:
    OnOffToggle()
        : ClusterCommand("toggle")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTROnOffClusterToggleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster toggleWithParams:params
                           completion:^(NSError * _Nullable error) {
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command OffWithEffect
 */
class OnOffOffWithEffect : public ClusterCommand {
public:
    OnOffOffWithEffect()
        : ClusterCommand("off-with-effect")
    {
        AddArgument("EffectId", 0, UINT8_MAX, &mRequest.effectId);
        AddArgument("EffectVariant", 0, UINT8_MAX, &mRequest.effectVariant);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) command (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTROnOffClusterOffWithEffectParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.effectId = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.effectId)];
        params.effectVariant = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.effectVariant)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster offWithEffectWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OnOff::Commands::OffWithEffect::Type mRequest;
};

/*
 * Command OnWithRecallGlobalScene
 */
class OnOffOnWithRecallGlobalScene : public ClusterCommand {
public:
    OnOffOnWithRecallGlobalScene()
        : ClusterCommand("on-with-recall-global-scene")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) command (0x00000041) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTROnOffClusterOnWithRecallGlobalSceneParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster onWithRecallGlobalSceneWithParams:params
                                            completion:^(NSError * _Nullable error) {
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command OnWithTimedOff
 */
class OnOffOnWithTimedOff : public ClusterCommand {
public:
    OnOffOnWithTimedOff()
        : ClusterCommand("on-with-timed-off")
    {
        AddArgument("OnOffControl", 0, UINT8_MAX, &mRequest.onOffControl);
        AddArgument("OnTime", 0, UINT16_MAX, &mRequest.onTime);
        AddArgument("OffWaitTime", 0, UINT16_MAX, &mRequest.offWaitTime);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) command (0x00000042) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTROnOffClusterOnWithTimedOffParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.onOffControl = [NSNumber numberWithUnsignedChar:mRequest.onOffControl.Raw()];
        params.onTime = [NSNumber numberWithUnsignedShort:mRequest.onTime];
        params.offWaitTime = [NSNumber numberWithUnsignedShort:mRequest.offWaitTime];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster onWithTimedOffWithParams:params
                                   completion:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OnOff::Commands::OnWithTimedOff::Type mRequest;
};

/*
 * Attribute OnOff
 */
class ReadOnOffOnOff : public ReadAttribute {
public:
    ReadOnOffOnOff()
        : ReadAttribute("on-off")
    {
    }

    ~ReadOnOffOnOff() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeOnOffWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.OnOff response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff OnOff read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffOnOff : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffOnOff()
        : SubscribeAttribute("on-off")
    {
    }

    ~SubscribeAttributeOnOffOnOff() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOnOffWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.OnOff response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GlobalSceneControl
 */
class ReadOnOffGlobalSceneControl : public ReadAttribute {
public:
    ReadOnOffGlobalSceneControl()
        : ReadAttribute("global-scene-control")
    {
    }

    ~ReadOnOffGlobalSceneControl() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x00004000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeGlobalSceneControlWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.GlobalSceneControl response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff GlobalSceneControl read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffGlobalSceneControl : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffGlobalSceneControl()
        : SubscribeAttribute("global-scene-control")
    {
    }

    ~SubscribeAttributeOnOffGlobalSceneControl() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGlobalSceneControlWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.GlobalSceneControl response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OnTime
 */
class ReadOnOffOnTime : public ReadAttribute {
public:
    ReadOnOffOnTime()
        : ReadAttribute("on-time")
    {
    }

    ~ReadOnOffOnTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x00004001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeOnTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.OnTime response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff OnTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOnOffOnTime : public WriteAttribute {
public:
    WriteOnOffOnTime()
        : WriteAttribute("on-time")
    {
        AddArgument("attr-name", "on-time");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOnOffOnTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) WriteAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOnTimeWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("OnOff OnTime write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOnOffOnTime : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffOnTime()
        : SubscribeAttribute("on-time")
    {
    }

    ~SubscribeAttributeOnOffOnTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOnTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.OnTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OffWaitTime
 */
class ReadOnOffOffWaitTime : public ReadAttribute {
public:
    ReadOnOffOffWaitTime()
        : ReadAttribute("off-wait-time")
    {
    }

    ~ReadOnOffOffWaitTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x00004002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeOffWaitTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.OffWaitTime response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff OffWaitTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOnOffOffWaitTime : public WriteAttribute {
public:
    WriteOnOffOffWaitTime()
        : WriteAttribute("off-wait-time")
    {
        AddArgument("attr-name", "off-wait-time");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOnOffOffWaitTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) WriteAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOffWaitTimeWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("OnOff OffWaitTime write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOnOffOffWaitTime : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffOffWaitTime()
        : SubscribeAttribute("off-wait-time")
    {
    }

    ~SubscribeAttributeOnOffOffWaitTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOffWaitTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.OffWaitTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartUpOnOff
 */
class ReadOnOffStartUpOnOff : public ReadAttribute {
public:
    ReadOnOffStartUpOnOff()
        : ReadAttribute("start-up-on-off")
    {
    }

    ~ReadOnOffStartUpOnOff() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x00004003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeStartUpOnOffWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.StartUpOnOff response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff StartUpOnOff read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOnOffStartUpOnOff : public WriteAttribute {
public:
    WriteOnOffStartUpOnOff()
        : WriteAttribute("start-up-on-off")
    {
        AddArgument("attr-name", "start-up-on-off");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOnOffStartUpOnOff() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) WriteAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeStartUpOnOffWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("OnOff StartUpOnOff write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOnOffStartUpOnOff : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffStartUpOnOff()
        : SubscribeAttribute("start-up-on-off")
    {
    }

    ~SubscribeAttributeOnOffStartUpOnOff() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStartUpOnOffWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.StartUpOnOff response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOnOffGeneratedCommandList : public ReadAttribute {
public:
    ReadOnOffGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOnOffGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOnOffGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOnOffAcceptedCommandList : public ReadAttribute {
public:
    ReadOnOffAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOnOffAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOnOffAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOnOffAttributeList : public ReadAttribute {
public:
    ReadOnOffAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOnOffAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOnOffAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOnOffFeatureMap : public ReadAttribute {
public:
    ReadOnOffFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOnOffFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOnOffFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOnOffClusterRevision : public ReadAttribute {
public:
    ReadOnOffClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOnOffClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOff.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOff ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOnOffClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000006) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOff * cluster = [[MTRBaseClusterOnOff alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOff.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OnOffSwitchConfiguration                                    | 0x0007 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * SwitchType                                                        | 0x0000 |
| * SwitchActions                                                     | 0x0010 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute SwitchType
 */
class ReadOnOffSwitchConfigurationSwitchType : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationSwitchType()
        : ReadAttribute("switch-type")
    {
    }

    ~ReadOnOffSwitchConfigurationSwitchType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSwitchTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.SwitchType response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration SwitchType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffSwitchConfigurationSwitchType : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationSwitchType()
        : SubscribeAttribute("switch-type")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationSwitchType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSwitchTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.SwitchType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SwitchActions
 */
class ReadOnOffSwitchConfigurationSwitchActions : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationSwitchActions()
        : ReadAttribute("switch-actions")
    {
    }

    ~ReadOnOffSwitchConfigurationSwitchActions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSwitchActionsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.SwitchActions response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration SwitchActions read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOnOffSwitchConfigurationSwitchActions : public WriteAttribute {
public:
    WriteOnOffSwitchConfigurationSwitchActions()
        : WriteAttribute("switch-actions")
    {
        AddArgument("attr-name", "switch-actions");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOnOffSwitchConfigurationSwitchActions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSwitchActionsWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("OnOffSwitchConfiguration SwitchActions write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOnOffSwitchConfigurationSwitchActions : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationSwitchActions()
        : SubscribeAttribute("switch-actions")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationSwitchActions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSwitchActionsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.SwitchActions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOnOffSwitchConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOnOffSwitchConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffSwitchConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOnOffSwitchConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOnOffSwitchConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffSwitchConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOnOffSwitchConfigurationAttributeList : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOnOffSwitchConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffSwitchConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOnOffSwitchConfigurationFeatureMap : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOnOffSwitchConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffSwitchConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOnOffSwitchConfigurationClusterRevision : public ReadAttribute {
public:
    ReadOnOffSwitchConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOnOffSwitchConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OnOffSwitchConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OnOffSwitchConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOnOffSwitchConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOnOffSwitchConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOnOffSwitchConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000007) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOnOffSwitchConfiguration * cluster =
            [[MTRBaseClusterOnOffSwitchConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OnOffSwitchConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster LevelControl                                                | 0x0008 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * MoveToLevel                                                       |   0x00 |
| * Move                                                              |   0x01 |
| * Step                                                              |   0x02 |
| * Stop                                                              |   0x03 |
| * MoveToLevelWithOnOff                                              |   0x04 |
| * MoveWithOnOff                                                     |   0x05 |
| * StepWithOnOff                                                     |   0x06 |
| * StopWithOnOff                                                     |   0x07 |
| * MoveToClosestFrequency                                            |   0x08 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * CurrentLevel                                                      | 0x0000 |
| * RemainingTime                                                     | 0x0001 |
| * MinLevel                                                          | 0x0002 |
| * MaxLevel                                                          | 0x0003 |
| * CurrentFrequency                                                  | 0x0004 |
| * MinFrequency                                                      | 0x0005 |
| * MaxFrequency                                                      | 0x0006 |
| * Options                                                           | 0x000F |
| * OnOffTransitionTime                                               | 0x0010 |
| * OnLevel                                                           | 0x0011 |
| * OnTransitionTime                                                  | 0x0012 |
| * OffTransitionTime                                                 | 0x0013 |
| * DefaultMoveRate                                                   | 0x0014 |
| * StartUpCurrentLevel                                               | 0x4000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command MoveToLevel
 */
class LevelControlMoveToLevel : public ClusterCommand {
public:
    LevelControlMoveToLevel()
        : ClusterCommand("move-to-level")
    {
        AddArgument("Level", 0, UINT8_MAX, &mRequest.level);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterMoveToLevelParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.level = [NSNumber numberWithUnsignedChar:mRequest.level];
        if (mRequest.transitionTime.IsNull()) {
            params.transitionTime = nil;
        } else {
            params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime.Value()];
        }
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToLevelWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::MoveToLevel::Type mRequest;
};

/*
 * Command Move
 */
class LevelControlMove : public ClusterCommand {
public:
    LevelControlMove()
        : ClusterCommand("move")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT8_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterMoveParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.moveMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.moveMode)];
        if (mRequest.rate.IsNull()) {
            params.rate = nil;
        } else {
            params.rate = [NSNumber numberWithUnsignedChar:mRequest.rate.Value()];
        }
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveWithParams:params
                         completion:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::Move::Type mRequest;
};

/*
 * Command Step
 */
class LevelControlStep : public ClusterCommand {
public:
    LevelControlStep()
        : ClusterCommand("step")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT8_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterStepParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.stepMode)];
        params.stepSize = [NSNumber numberWithUnsignedChar:mRequest.stepSize];
        if (mRequest.transitionTime.IsNull()) {
            params.transitionTime = nil;
        } else {
            params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime.Value()];
        }
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stepWithParams:params
                         completion:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::Step::Type mRequest;
};

/*
 * Command Stop
 */
class LevelControlStop : public ClusterCommand {
public:
    LevelControlStop()
        : ClusterCommand("stop")
    {
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterStopParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopWithParams:params
                         completion:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::Stop::Type mRequest;
};

/*
 * Command MoveToLevelWithOnOff
 */
class LevelControlMoveToLevelWithOnOff : public ClusterCommand {
public:
    LevelControlMoveToLevelWithOnOff()
        : ClusterCommand("move-to-level-with-on-off")
    {
        AddArgument("Level", 0, UINT8_MAX, &mRequest.level);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterMoveToLevelWithOnOffParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.level = [NSNumber numberWithUnsignedChar:mRequest.level];
        if (mRequest.transitionTime.IsNull()) {
            params.transitionTime = nil;
        } else {
            params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime.Value()];
        }
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToLevelWithOnOffWithParams:params
                                         completion:^(NSError * _Nullable error) {
                                             responsesNeeded--;
                                             if (error != nil) {
                                                 mError = error;
                                                 LogNSError("Error", error);
                                             }
                                             if (responsesNeeded == 0) {
                                                 SetCommandExitStatus(mError);
                                             }
                                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Type mRequest;
};

/*
 * Command MoveWithOnOff
 */
class LevelControlMoveWithOnOff : public ClusterCommand {
public:
    LevelControlMoveWithOnOff()
        : ClusterCommand("move-with-on-off")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT8_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterMoveWithOnOffParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.moveMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.moveMode)];
        if (mRequest.rate.IsNull()) {
            params.rate = nil;
        } else {
            params.rate = [NSNumber numberWithUnsignedChar:mRequest.rate.Value()];
        }
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveWithOnOffWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::MoveWithOnOff::Type mRequest;
};

/*
 * Command StepWithOnOff
 */
class LevelControlStepWithOnOff : public ClusterCommand {
public:
    LevelControlStepWithOnOff()
        : ClusterCommand("step-with-on-off")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT8_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterStepWithOnOffParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.stepMode)];
        params.stepSize = [NSNumber numberWithUnsignedChar:mRequest.stepSize];
        if (mRequest.transitionTime.IsNull()) {
            params.transitionTime = nil;
        } else {
            params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime.Value()];
        }
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stepWithOnOffWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::StepWithOnOff::Type mRequest;
};

/*
 * Command StopWithOnOff
 */
class LevelControlStopWithOnOff : public ClusterCommand {
public:
    LevelControlStopWithOnOff()
        : ClusterCommand("stop-with-on-off")
    {
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterStopWithOnOffParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopWithOnOffWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::StopWithOnOff::Type mRequest;
};

/*
 * Command MoveToClosestFrequency
 */
class LevelControlMoveToClosestFrequency : public ClusterCommand {
public:
    LevelControlMoveToClosestFrequency()
        : ClusterCommand("move-to-closest-frequency")
    {
        AddArgument("Frequency", 0, UINT16_MAX, &mRequest.frequency);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRLevelControlClusterMoveToClosestFrequencyParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.frequency = [NSNumber numberWithUnsignedShort:mRequest.frequency];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToClosestFrequencyWithParams:params
                                           completion:^(NSError * _Nullable error) {
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::LevelControl::Commands::MoveToClosestFrequency::Type mRequest;
};

/*
 * Attribute CurrentLevel
 */
class ReadLevelControlCurrentLevel : public ReadAttribute {
public:
    ReadLevelControlCurrentLevel()
        : ReadAttribute("current-level")
    {
    }

    ~ReadLevelControlCurrentLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.CurrentLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl CurrentLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlCurrentLevel : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlCurrentLevel()
        : SubscribeAttribute("current-level")
    {
    }

    ~SubscribeAttributeLevelControlCurrentLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.CurrentLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RemainingTime
 */
class ReadLevelControlRemainingTime : public ReadAttribute {
public:
    ReadLevelControlRemainingTime()
        : ReadAttribute("remaining-time")
    {
    }

    ~ReadLevelControlRemainingTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeRemainingTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.RemainingTime response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl RemainingTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlRemainingTime : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlRemainingTime()
        : SubscribeAttribute("remaining-time")
    {
    }

    ~SubscribeAttributeLevelControlRemainingTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRemainingTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.RemainingTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinLevel
 */
class ReadLevelControlMinLevel : public ReadAttribute {
public:
    ReadLevelControlMinLevel()
        : ReadAttribute("min-level")
    {
    }

    ~ReadLevelControlMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeMinLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.MinLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl MinLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlMinLevel : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlMinLevel()
        : SubscribeAttribute("min-level")
    {
    }

    ~SubscribeAttributeLevelControlMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.MinLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxLevel
 */
class ReadLevelControlMaxLevel : public ReadAttribute {
public:
    ReadLevelControlMaxLevel()
        : ReadAttribute("max-level")
    {
    }

    ~ReadLevelControlMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeMaxLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.MaxLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl MaxLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlMaxLevel : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlMaxLevel()
        : SubscribeAttribute("max-level")
    {
    }

    ~SubscribeAttributeLevelControlMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.MaxLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentFrequency
 */
class ReadLevelControlCurrentFrequency : public ReadAttribute {
public:
    ReadLevelControlCurrentFrequency()
        : ReadAttribute("current-frequency")
    {
    }

    ~ReadLevelControlCurrentFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentFrequencyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.CurrentFrequency response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl CurrentFrequency read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlCurrentFrequency : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlCurrentFrequency()
        : SubscribeAttribute("current-frequency")
    {
    }

    ~SubscribeAttributeLevelControlCurrentFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentFrequencyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.CurrentFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinFrequency
 */
class ReadLevelControlMinFrequency : public ReadAttribute {
public:
    ReadLevelControlMinFrequency()
        : ReadAttribute("min-frequency")
    {
    }

    ~ReadLevelControlMinFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeMinFrequencyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.MinFrequency response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl MinFrequency read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlMinFrequency : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlMinFrequency()
        : SubscribeAttribute("min-frequency")
    {
    }

    ~SubscribeAttributeLevelControlMinFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinFrequencyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.MinFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxFrequency
 */
class ReadLevelControlMaxFrequency : public ReadAttribute {
public:
    ReadLevelControlMaxFrequency()
        : ReadAttribute("max-frequency")
    {
    }

    ~ReadLevelControlMaxFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeMaxFrequencyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.MaxFrequency response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl MaxFrequency read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlMaxFrequency : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlMaxFrequency()
        : SubscribeAttribute("max-frequency")
    {
    }

    ~SubscribeAttributeLevelControlMaxFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxFrequencyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.MaxFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Options
 */
class ReadLevelControlOptions : public ReadAttribute {
public:
    ReadLevelControlOptions()
        : ReadAttribute("options")
    {
    }

    ~ReadLevelControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeOptionsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.Options response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl Options read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlOptions : public WriteAttribute {
public:
    WriteLevelControlOptions()
        : WriteAttribute("options")
    {
        AddArgument("attr-name", "options");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOptionsWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("LevelControl Options write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeLevelControlOptions : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlOptions()
        : SubscribeAttribute("options")
    {
    }

    ~SubscribeAttributeLevelControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOptionsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.Options response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OnOffTransitionTime
 */
class ReadLevelControlOnOffTransitionTime : public ReadAttribute {
public:
    ReadLevelControlOnOffTransitionTime()
        : ReadAttribute("on-off-transition-time")
    {
    }

    ~ReadLevelControlOnOffTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeOnOffTransitionTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.OnOffTransitionTime response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl OnOffTransitionTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlOnOffTransitionTime : public WriteAttribute {
public:
    WriteLevelControlOnOffTransitionTime()
        : WriteAttribute("on-off-transition-time")
    {
        AddArgument("attr-name", "on-off-transition-time");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlOnOffTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOnOffTransitionTimeWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("LevelControl OnOffTransitionTime write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeLevelControlOnOffTransitionTime : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlOnOffTransitionTime()
        : SubscribeAttribute("on-off-transition-time")
    {
    }

    ~SubscribeAttributeLevelControlOnOffTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOnOffTransitionTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.OnOffTransitionTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OnLevel
 */
class ReadLevelControlOnLevel : public ReadAttribute {
public:
    ReadLevelControlOnLevel()
        : ReadAttribute("on-level")
    {
    }

    ~ReadLevelControlOnLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeOnLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.OnLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl OnLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlOnLevel : public WriteAttribute {
public:
    WriteLevelControlOnLevel()
        : WriteAttribute("on-level")
    {
        AddArgument("attr-name", "on-level");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlOnLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOnLevelWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("LevelControl OnLevel write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeLevelControlOnLevel : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlOnLevel()
        : SubscribeAttribute("on-level")
    {
    }

    ~SubscribeAttributeLevelControlOnLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOnLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.OnLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OnTransitionTime
 */
class ReadLevelControlOnTransitionTime : public ReadAttribute {
public:
    ReadLevelControlOnTransitionTime()
        : ReadAttribute("on-transition-time")
    {
    }

    ~ReadLevelControlOnTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeOnTransitionTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.OnTransitionTime response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl OnTransitionTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlOnTransitionTime : public WriteAttribute {
public:
    WriteLevelControlOnTransitionTime()
        : WriteAttribute("on-transition-time")
    {
        AddArgument("attr-name", "on-transition-time");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlOnTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOnTransitionTimeWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("LevelControl OnTransitionTime write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeLevelControlOnTransitionTime : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlOnTransitionTime()
        : SubscribeAttribute("on-transition-time")
    {
    }

    ~SubscribeAttributeLevelControlOnTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOnTransitionTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.OnTransitionTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OffTransitionTime
 */
class ReadLevelControlOffTransitionTime : public ReadAttribute {
public:
    ReadLevelControlOffTransitionTime()
        : ReadAttribute("off-transition-time")
    {
    }

    ~ReadLevelControlOffTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeOffTransitionTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.OffTransitionTime response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl OffTransitionTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlOffTransitionTime : public WriteAttribute {
public:
    WriteLevelControlOffTransitionTime()
        : WriteAttribute("off-transition-time")
    {
        AddArgument("attr-name", "off-transition-time");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlOffTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOffTransitionTimeWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("LevelControl OffTransitionTime write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeLevelControlOffTransitionTime : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlOffTransitionTime()
        : SubscribeAttribute("off-transition-time")
    {
    }

    ~SubscribeAttributeLevelControlOffTransitionTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOffTransitionTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.OffTransitionTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DefaultMoveRate
 */
class ReadLevelControlDefaultMoveRate : public ReadAttribute {
public:
    ReadLevelControlDefaultMoveRate()
        : ReadAttribute("default-move-rate")
    {
    }

    ~ReadLevelControlDefaultMoveRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeDefaultMoveRateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.DefaultMoveRate response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl DefaultMoveRate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlDefaultMoveRate : public WriteAttribute {
public:
    WriteLevelControlDefaultMoveRate()
        : WriteAttribute("default-move-rate")
    {
        AddArgument("attr-name", "default-move-rate");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlDefaultMoveRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeDefaultMoveRateWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("LevelControl DefaultMoveRate write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeLevelControlDefaultMoveRate : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlDefaultMoveRate()
        : SubscribeAttribute("default-move-rate")
    {
    }

    ~SubscribeAttributeLevelControlDefaultMoveRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDefaultMoveRateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.DefaultMoveRate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartUpCurrentLevel
 */
class ReadLevelControlStartUpCurrentLevel : public ReadAttribute {
public:
    ReadLevelControlStartUpCurrentLevel()
        : ReadAttribute("start-up-current-level")
    {
    }

    ~ReadLevelControlStartUpCurrentLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x00004000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeStartUpCurrentLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.StartUpCurrentLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl StartUpCurrentLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLevelControlStartUpCurrentLevel : public WriteAttribute {
public:
    WriteLevelControlStartUpCurrentLevel()
        : WriteAttribute("start-up-current-level")
    {
        AddArgument("attr-name", "start-up-current-level");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLevelControlStartUpCurrentLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) WriteAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeStartUpCurrentLevelWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("LevelControl StartUpCurrentLevel write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeLevelControlStartUpCurrentLevel : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlStartUpCurrentLevel()
        : SubscribeAttribute("start-up-current-level")
    {
    }

    ~SubscribeAttributeLevelControlStartUpCurrentLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStartUpCurrentLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.StartUpCurrentLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadLevelControlGeneratedCommandList : public ReadAttribute {
public:
    ReadLevelControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadLevelControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeLevelControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadLevelControlAcceptedCommandList : public ReadAttribute {
public:
    ReadLevelControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadLevelControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeLevelControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadLevelControlAttributeList : public ReadAttribute {
public:
    ReadLevelControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadLevelControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeLevelControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadLevelControlFeatureMap : public ReadAttribute {
public:
    ReadLevelControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadLevelControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeLevelControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadLevelControlClusterRevision : public ReadAttribute {
public:
    ReadLevelControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadLevelControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LevelControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("LevelControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLevelControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeLevelControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeLevelControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000008) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLevelControl * cluster = [[MTRBaseClusterLevelControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LevelControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BinaryInputBasic                                            | 0x000F |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ActiveText                                                        | 0x0004 |
| * Description                                                       | 0x001C |
| * InactiveText                                                      | 0x002E |
| * OutOfService                                                      | 0x0051 |
| * Polarity                                                          | 0x0054 |
| * PresentValue                                                      | 0x0055 |
| * Reliability                                                       | 0x0067 |
| * StatusFlags                                                       | 0x006F |
| * ApplicationType                                                   | 0x0100 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute ActiveText
 */
class ReadBinaryInputBasicActiveText : public ReadAttribute {
public:
    ReadBinaryInputBasicActiveText()
        : ReadAttribute("active-text")
    {
    }

    ~ReadBinaryInputBasicActiveText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeActiveTextWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.ActiveText response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic ActiveText read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBinaryInputBasicActiveText : public WriteAttribute {
public:
    WriteBinaryInputBasicActiveText()
        : WriteAttribute("active-text")
    {
        AddArgument("attr-name", "active-text");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBinaryInputBasicActiveText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeActiveTextWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("BinaryInputBasic ActiveText write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBinaryInputBasicActiveText : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicActiveText()
        : SubscribeAttribute("active-text")
    {
    }

    ~SubscribeAttributeBinaryInputBasicActiveText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveTextWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.ActiveText response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Description
 */
class ReadBinaryInputBasicDescription : public ReadAttribute {
public:
    ReadBinaryInputBasicDescription()
        : ReadAttribute("description")
    {
    }

    ~ReadBinaryInputBasicDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeDescriptionWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.Description response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic Description read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBinaryInputBasicDescription : public WriteAttribute {
public:
    WriteBinaryInputBasicDescription()
        : WriteAttribute("description")
    {
        AddArgument("attr-name", "description");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBinaryInputBasicDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) WriteAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeDescriptionWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("BinaryInputBasic Description write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBinaryInputBasicDescription : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicDescription()
        : SubscribeAttribute("description")
    {
    }

    ~SubscribeAttributeBinaryInputBasicDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDescriptionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.Description response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InactiveText
 */
class ReadBinaryInputBasicInactiveText : public ReadAttribute {
public:
    ReadBinaryInputBasicInactiveText()
        : ReadAttribute("inactive-text")
    {
    }

    ~ReadBinaryInputBasicInactiveText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000002E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeInactiveTextWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.InactiveText response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic InactiveText read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBinaryInputBasicInactiveText : public WriteAttribute {
public:
    WriteBinaryInputBasicInactiveText()
        : WriteAttribute("inactive-text")
    {
        AddArgument("attr-name", "inactive-text");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBinaryInputBasicInactiveText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) WriteAttribute (0x0000002E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeInactiveTextWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("BinaryInputBasic InactiveText write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBinaryInputBasicInactiveText : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicInactiveText()
        : SubscribeAttribute("inactive-text")
    {
    }

    ~SubscribeAttributeBinaryInputBasicInactiveText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000002E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInactiveTextWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.InactiveText response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OutOfService
 */
class ReadBinaryInputBasicOutOfService : public ReadAttribute {
public:
    ReadBinaryInputBasicOutOfService()
        : ReadAttribute("out-of-service")
    {
    }

    ~ReadBinaryInputBasicOutOfService() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x00000051) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeOutOfServiceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.OutOfService response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic OutOfService read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBinaryInputBasicOutOfService : public WriteAttribute {
public:
    WriteBinaryInputBasicOutOfService()
        : WriteAttribute("out-of-service")
    {
        AddArgument("attr-name", "out-of-service");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBinaryInputBasicOutOfService() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) WriteAttribute (0x00000051) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeOutOfServiceWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("BinaryInputBasic OutOfService write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeBinaryInputBasicOutOfService : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicOutOfService()
        : SubscribeAttribute("out-of-service")
    {
    }

    ~SubscribeAttributeBinaryInputBasicOutOfService() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x00000051) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOutOfServiceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.OutOfService response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Polarity
 */
class ReadBinaryInputBasicPolarity : public ReadAttribute {
public:
    ReadBinaryInputBasicPolarity()
        : ReadAttribute("polarity")
    {
    }

    ~ReadBinaryInputBasicPolarity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x00000054) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePolarityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.Polarity response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic Polarity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicPolarity : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicPolarity()
        : SubscribeAttribute("polarity")
    {
    }

    ~SubscribeAttributeBinaryInputBasicPolarity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x00000054) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePolarityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.Polarity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PresentValue
 */
class ReadBinaryInputBasicPresentValue : public ReadAttribute {
public:
    ReadBinaryInputBasicPresentValue()
        : ReadAttribute("present-value")
    {
    }

    ~ReadBinaryInputBasicPresentValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x00000055) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePresentValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.PresentValue response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic PresentValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBinaryInputBasicPresentValue : public WriteAttribute {
public:
    WriteBinaryInputBasicPresentValue()
        : WriteAttribute("present-value")
    {
        AddArgument("attr-name", "present-value");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBinaryInputBasicPresentValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) WriteAttribute (0x00000055) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributePresentValueWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("BinaryInputBasic PresentValue write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeBinaryInputBasicPresentValue : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicPresentValue()
        : SubscribeAttribute("present-value")
    {
    }

    ~SubscribeAttributeBinaryInputBasicPresentValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x00000055) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePresentValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.PresentValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Reliability
 */
class ReadBinaryInputBasicReliability : public ReadAttribute {
public:
    ReadBinaryInputBasicReliability()
        : ReadAttribute("reliability")
    {
    }

    ~ReadBinaryInputBasicReliability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x00000067) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeReliabilityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.Reliability response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic Reliability read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBinaryInputBasicReliability : public WriteAttribute {
public:
    WriteBinaryInputBasicReliability()
        : WriteAttribute("reliability")
    {
        AddArgument("attr-name", "reliability");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBinaryInputBasicReliability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) WriteAttribute (0x00000067) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeReliabilityWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("BinaryInputBasic Reliability write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBinaryInputBasicReliability : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicReliability()
        : SubscribeAttribute("reliability")
    {
    }

    ~SubscribeAttributeBinaryInputBasicReliability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x00000067) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReliabilityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.Reliability response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StatusFlags
 */
class ReadBinaryInputBasicStatusFlags : public ReadAttribute {
public:
    ReadBinaryInputBasicStatusFlags()
        : ReadAttribute("status-flags")
    {
    }

    ~ReadBinaryInputBasicStatusFlags() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000006F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeStatusFlagsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.StatusFlags response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic StatusFlags read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicStatusFlags : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicStatusFlags()
        : SubscribeAttribute("status-flags")
    {
    }

    ~SubscribeAttributeBinaryInputBasicStatusFlags() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000006F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStatusFlagsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.StatusFlags response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApplicationType
 */
class ReadBinaryInputBasicApplicationType : public ReadAttribute {
public:
    ReadBinaryInputBasicApplicationType()
        : ReadAttribute("application-type")
    {
    }

    ~ReadBinaryInputBasicApplicationType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x00000100) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.ApplicationType response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic ApplicationType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicApplicationType : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicApplicationType()
        : SubscribeAttribute("application-type")
    {
    }

    ~SubscribeAttributeBinaryInputBasicApplicationType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x00000100) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApplicationTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.ApplicationType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBinaryInputBasicGeneratedCommandList : public ReadAttribute {
public:
    ReadBinaryInputBasicGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBinaryInputBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBinaryInputBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBinaryInputBasicAcceptedCommandList : public ReadAttribute {
public:
    ReadBinaryInputBasicAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBinaryInputBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBinaryInputBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBinaryInputBasicAttributeList : public ReadAttribute {
public:
    ReadBinaryInputBasicAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBinaryInputBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBinaryInputBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBinaryInputBasicFeatureMap : public ReadAttribute {
public:
    ReadBinaryInputBasicFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBinaryInputBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBinaryInputBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBinaryInputBasicClusterRevision : public ReadAttribute {
public:
    ReadBinaryInputBasicClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBinaryInputBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BinaryInputBasic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BinaryInputBasic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBinaryInputBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBinaryInputBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBinaryInputBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000000F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinaryInputBasic * cluster = [[MTRBaseClusterBinaryInputBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BinaryInputBasic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Descriptor                                                  | 0x001D |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * DeviceTypeList                                                    | 0x0000 |
| * ServerList                                                        | 0x0001 |
| * ClientList                                                        | 0x0002 |
| * PartsList                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute DeviceTypeList
 */
class ReadDescriptorDeviceTypeList : public ReadAttribute {
public:
    ReadDescriptorDeviceTypeList()
        : ReadAttribute("device-type-list")
    {
    }

    ~ReadDescriptorDeviceTypeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeDeviceTypeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.DeviceTypeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor DeviceTypeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorDeviceTypeList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorDeviceTypeList()
        : SubscribeAttribute("device-type-list")
    {
    }

    ~SubscribeAttributeDescriptorDeviceTypeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDeviceTypeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.DeviceTypeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ServerList
 */
class ReadDescriptorServerList : public ReadAttribute {
public:
    ReadDescriptorServerList()
        : ReadAttribute("server-list")
    {
    }

    ~ReadDescriptorServerList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeServerListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.ServerList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor ServerList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorServerList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorServerList()
        : SubscribeAttribute("server-list")
    {
    }

    ~SubscribeAttributeDescriptorServerList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeServerListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.ServerList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClientList
 */
class ReadDescriptorClientList : public ReadAttribute {
public:
    ReadDescriptorClientList()
        : ReadAttribute("client-list")
    {
    }

    ~ReadDescriptorClientList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClientListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.ClientList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor ClientList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorClientList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorClientList()
        : SubscribeAttribute("client-list")
    {
    }

    ~SubscribeAttributeDescriptorClientList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClientListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.ClientList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartsList
 */
class ReadDescriptorPartsList : public ReadAttribute {
public:
    ReadDescriptorPartsList()
        : ReadAttribute("parts-list")
    {
    }

    ~ReadDescriptorPartsList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributePartsListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.PartsList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor PartsList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorPartsList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorPartsList()
        : SubscribeAttribute("parts-list")
    {
    }

    ~SubscribeAttributeDescriptorPartsList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePartsListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.PartsList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadDescriptorGeneratedCommandList : public ReadAttribute {
public:
    ReadDescriptorGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadDescriptorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeDescriptorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadDescriptorAcceptedCommandList : public ReadAttribute {
public:
    ReadDescriptorAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadDescriptorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeDescriptorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadDescriptorAttributeList : public ReadAttribute {
public:
    ReadDescriptorAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadDescriptorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeDescriptorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadDescriptorFeatureMap : public ReadAttribute {
public:
    ReadDescriptorFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadDescriptorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeDescriptorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadDescriptorClusterRevision : public ReadAttribute {
public:
    ReadDescriptorClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadDescriptorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Descriptor.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Descriptor ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDescriptorClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeDescriptorClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeDescriptorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001D) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDescriptor * cluster = [[MTRBaseClusterDescriptor alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Descriptor.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Binding                                                     | 0x001E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Binding                                                           | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Binding
 */
class ReadBindingBinding : public ReadAttribute {
public:
    ReadBindingBinding()
        : ReadAttribute("binding")
    {
    }

    ~ReadBindingBinding() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeBindingWithParams:params
                                     completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                         NSLog(@"Binding.Binding response %@", [value description]);
                                         if (error != nil) {
                                             LogNSError("Binding Binding read Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }
};

class WriteBindingBinding : public WriteAttribute {
public:
    WriteBindingBinding()
        : WriteAttribute("binding")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "binding");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteBindingBinding() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRBindingClusterTargetStruct * newElement_0;
                newElement_0 = [MTRBindingClusterTargetStruct new];
                if (entry_0.node.HasValue()) {
                    newElement_0.node = [NSNumber numberWithUnsignedLongLong:entry_0.node.Value()];
                } else {
                    newElement_0.node = nil;
                }
                if (entry_0.group.HasValue()) {
                    newElement_0.group = [NSNumber numberWithUnsignedShort:entry_0.group.Value()];
                } else {
                    newElement_0.group = nil;
                }
                if (entry_0.endpoint.HasValue()) {
                    newElement_0.endpoint = [NSNumber numberWithUnsignedShort:entry_0.endpoint.Value()];
                } else {
                    newElement_0.endpoint = nil;
                }
                if (entry_0.cluster.HasValue()) {
                    newElement_0.cluster = [NSNumber numberWithUnsignedInt:entry_0.cluster.Value()];
                } else {
                    newElement_0.cluster = nil;
                }
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeBindingWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("Binding Binding write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::Binding::Structs::TargetStruct::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::Binding::Structs::TargetStruct::Type>> mComplex;
};

class SubscribeAttributeBindingBinding : public SubscribeAttribute {
public:
    SubscribeAttributeBindingBinding()
        : SubscribeAttribute("binding")
    {
    }

    ~SubscribeAttributeBindingBinding() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBindingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.Binding response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBindingGeneratedCommandList : public ReadAttribute {
public:
    ReadBindingGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBindingGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Binding.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Binding GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBindingGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBindingGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBindingGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBindingAcceptedCommandList : public ReadAttribute {
public:
    ReadBindingAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBindingAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Binding.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Binding AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBindingAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBindingAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBindingAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBindingAttributeList : public ReadAttribute {
public:
    ReadBindingAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBindingAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Binding.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Binding AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBindingAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBindingAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBindingAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBindingFeatureMap : public ReadAttribute {
public:
    ReadBindingFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBindingFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Binding.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Binding FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBindingFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBindingFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBindingFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBindingClusterRevision : public ReadAttribute {
public:
    ReadBindingClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBindingClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Binding.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Binding ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBindingClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBindingClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBindingClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBinding * cluster = [[MTRBaseClusterBinding alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Binding.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AccessControl                                               | 0x001F |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Acl                                                               | 0x0000 |
| * Extension                                                         | 0x0001 |
| * SubjectsPerAccessControlEntry                                     | 0x0002 |
| * TargetsPerAccessControlEntry                                      | 0x0003 |
| * AccessControlEntriesPerFabric                                     | 0x0004 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * AccessControlEntryChanged                                         | 0x0000 |
| * AccessControlExtensionChanged                                     | 0x0001 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Acl
 */
class ReadAccessControlAcl : public ReadAttribute {
public:
    ReadAccessControlAcl()
        : ReadAttribute("acl")
    {
    }

    ~ReadAccessControlAcl() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeAclWithParams:params
                                 completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                     NSLog(@"AccessControl.Acl response %@", [value description]);
                                     if (error != nil) {
                                         LogNSError("AccessControl Acl read Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }
};

class WriteAccessControlAcl : public WriteAttribute {
public:
    WriteAccessControlAcl()
        : WriteAttribute("acl")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "acl");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteAccessControlAcl() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRAccessControlClusterAccessControlEntry * newElement_0;
                newElement_0 = [MTRAccessControlClusterAccessControlEntry new];
                newElement_0.privilege = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.privilege)];
                newElement_0.authMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.authMode)];
                if (entry_0.subjects.IsNull()) {
                    newElement_0.subjects = nil;
                } else {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.subjects.Value()) {
                            NSNumber * newElement_3;
                            newElement_3 = [NSNumber numberWithUnsignedLongLong:entry_3];
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.subjects = array_3;
                    }
                }
                if (entry_0.targets.IsNull()) {
                    newElement_0.targets = nil;
                } else {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.targets.Value()) {
                            MTRAccessControlClusterTarget * newElement_3;
                            newElement_3 = [MTRAccessControlClusterTarget new];
                            if (entry_3.cluster.IsNull()) {
                                newElement_3.cluster = nil;
                            } else {
                                newElement_3.cluster = [NSNumber numberWithUnsignedInt:entry_3.cluster.Value()];
                            }
                            if (entry_3.endpoint.IsNull()) {
                                newElement_3.endpoint = nil;
                            } else {
                                newElement_3.endpoint = [NSNumber numberWithUnsignedShort:entry_3.endpoint.Value()];
                            }
                            if (entry_3.deviceType.IsNull()) {
                                newElement_3.deviceType = nil;
                            } else {
                                newElement_3.deviceType = [NSNumber numberWithUnsignedInt:entry_3.deviceType.Value()];
                            }
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.targets = array_3;
                    }
                }
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeAclWithValue:value
                                     params:params
                                 completion:^(NSError * _Nullable error) {
                                     if (error != nil) {
                                         LogNSError("AccessControl Acl write Error", error);
                                     }
                                     SetCommandExitStatus(error);
                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::AccessControl::Structs::AccessControlEntry::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::AccessControl::Structs::AccessControlEntry::Type>>
        mComplex;
};

class SubscribeAttributeAccessControlAcl : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlAcl()
        : SubscribeAttribute("acl")
    {
    }

    ~SubscribeAttributeAccessControlAcl() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAclWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.Acl response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Extension
 */
class ReadAccessControlExtension : public ReadAttribute {
public:
    ReadAccessControlExtension()
        : ReadAttribute("extension")
    {
    }

    ~ReadAccessControlExtension() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeExtensionWithParams:params
                                       completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                           NSLog(@"AccessControl.Extension response %@", [value description]);
                                           if (error != nil) {
                                               LogNSError("AccessControl Extension read Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }
};

class WriteAccessControlExtension : public WriteAttribute {
public:
    WriteAccessControlExtension()
        : WriteAttribute("extension")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "extension");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteAccessControlExtension() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRAccessControlClusterExtensionEntry * newElement_0;
                newElement_0 = [MTRAccessControlClusterExtensionEntry new];
                newElement_0.data = [NSData dataWithBytes:entry_0.data.data() length:entry_0.data.size()];
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeExtensionWithValue:value
                                           params:params
                                       completion:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("AccessControl Extension write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::AccessControl::Structs::ExtensionEntry::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::AccessControl::Structs::ExtensionEntry::Type>>
        mComplex;
};

class SubscribeAttributeAccessControlExtension : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlExtension()
        : SubscribeAttribute("extension")
    {
    }

    ~SubscribeAttributeAccessControlExtension() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeExtensionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.Extension response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SubjectsPerAccessControlEntry
 */
class ReadAccessControlSubjectsPerAccessControlEntry : public ReadAttribute {
public:
    ReadAccessControlSubjectsPerAccessControlEntry()
        : ReadAttribute("subjects-per-access-control-entry")
    {
    }

    ~ReadAccessControlSubjectsPerAccessControlEntry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSubjectsPerAccessControlEntryWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.SubjectsPerAccessControlEntry response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl SubjectsPerAccessControlEntry read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlSubjectsPerAccessControlEntry : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlSubjectsPerAccessControlEntry()
        : SubscribeAttribute("subjects-per-access-control-entry")
    {
    }

    ~SubscribeAttributeAccessControlSubjectsPerAccessControlEntry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSubjectsPerAccessControlEntryWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.SubjectsPerAccessControlEntry response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TargetsPerAccessControlEntry
 */
class ReadAccessControlTargetsPerAccessControlEntry : public ReadAttribute {
public:
    ReadAccessControlTargetsPerAccessControlEntry()
        : ReadAttribute("targets-per-access-control-entry")
    {
    }

    ~ReadAccessControlTargetsPerAccessControlEntry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeTargetsPerAccessControlEntryWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.TargetsPerAccessControlEntry response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl TargetsPerAccessControlEntry read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlTargetsPerAccessControlEntry : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlTargetsPerAccessControlEntry()
        : SubscribeAttribute("targets-per-access-control-entry")
    {
    }

    ~SubscribeAttributeAccessControlTargetsPerAccessControlEntry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTargetsPerAccessControlEntryWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.TargetsPerAccessControlEntry response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AccessControlEntriesPerFabric
 */
class ReadAccessControlAccessControlEntriesPerFabric : public ReadAttribute {
public:
    ReadAccessControlAccessControlEntriesPerFabric()
        : ReadAttribute("access-control-entries-per-fabric")
    {
    }

    ~ReadAccessControlAccessControlEntriesPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAccessControlEntriesPerFabricWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.AccessControlEntriesPerFabric response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl AccessControlEntriesPerFabric read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlAccessControlEntriesPerFabric : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlAccessControlEntriesPerFabric()
        : SubscribeAttribute("access-control-entries-per-fabric")
    {
    }

    ~SubscribeAttributeAccessControlAccessControlEntriesPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAccessControlEntriesPerFabricWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.AccessControlEntriesPerFabric response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAccessControlGeneratedCommandList : public ReadAttribute {
public:
    ReadAccessControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAccessControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAccessControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAccessControlAcceptedCommandList : public ReadAttribute {
public:
    ReadAccessControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAccessControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAccessControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAccessControlAttributeList : public ReadAttribute {
public:
    ReadAccessControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAccessControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAccessControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAccessControlFeatureMap : public ReadAttribute {
public:
    ReadAccessControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAccessControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAccessControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAccessControlClusterRevision : public ReadAttribute {
public:
    ReadAccessControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAccessControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccessControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AccessControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccessControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAccessControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAccessControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000001F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccessControl * cluster = [[MTRBaseClusterAccessControl alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccessControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Actions                                                     | 0x0025 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * InstantAction                                                     |   0x00 |
| * InstantActionWithTransition                                       |   0x01 |
| * StartAction                                                       |   0x02 |
| * StartActionWithDuration                                           |   0x03 |
| * StopAction                                                        |   0x04 |
| * PauseAction                                                       |   0x05 |
| * PauseActionWithDuration                                           |   0x06 |
| * ResumeAction                                                      |   0x07 |
| * EnableAction                                                      |   0x08 |
| * EnableActionWithDuration                                          |   0x09 |
| * DisableAction                                                     |   0x0A |
| * DisableActionWithDuration                                         |   0x0B |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ActionList                                                        | 0x0000 |
| * EndpointLists                                                     | 0x0001 |
| * SetupURL                                                          | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateChanged                                                      | 0x0000 |
| * ActionFailed                                                      | 0x0001 |
\*----------------------------------------------------------------------------*/

/*
 * Command InstantAction
 */
class ActionsInstantAction : public ClusterCommand {
public:
    ActionsInstantAction()
        : ClusterCommand("instant-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterInstantActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster instantActionWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::InstantAction::Type mRequest;
};

/*
 * Command InstantActionWithTransition
 */
class ActionsInstantActionWithTransition : public ClusterCommand {
public:
    ActionsInstantActionWithTransition()
        : ClusterCommand("instant-action-with-transition")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterInstantActionWithTransitionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster instantActionWithTransitionWithParams:params
                                                completion:^(NSError * _Nullable error) {
                                                    responsesNeeded--;
                                                    if (error != nil) {
                                                        mError = error;
                                                        LogNSError("Error", error);
                                                    }
                                                    if (responsesNeeded == 0) {
                                                        SetCommandExitStatus(mError);
                                                    }
                                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::InstantActionWithTransition::Type mRequest;
};

/*
 * Command StartAction
 */
class ActionsStartAction : public ClusterCommand {
public:
    ActionsStartAction()
        : ClusterCommand("start-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterStartActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster startActionWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::StartAction::Type mRequest;
};

/*
 * Command StartActionWithDuration
 */
class ActionsStartActionWithDuration : public ClusterCommand {
public:
    ActionsStartActionWithDuration()
        : ClusterCommand("start-action-with-duration")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterStartActionWithDurationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        params.duration = [NSNumber numberWithUnsignedInt:mRequest.duration];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster startActionWithDurationWithParams:params
                                            completion:^(NSError * _Nullable error) {
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::StartActionWithDuration::Type mRequest;
};

/*
 * Command StopAction
 */
class ActionsStopAction : public ClusterCommand {
public:
    ActionsStopAction()
        : ClusterCommand("stop-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterStopActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopActionWithParams:params
                               completion:^(NSError * _Nullable error) {
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::StopAction::Type mRequest;
};

/*
 * Command PauseAction
 */
class ActionsPauseAction : public ClusterCommand {
public:
    ActionsPauseAction()
        : ClusterCommand("pause-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterPauseActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster pauseActionWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::PauseAction::Type mRequest;
};

/*
 * Command PauseActionWithDuration
 */
class ActionsPauseActionWithDuration : public ClusterCommand {
public:
    ActionsPauseActionWithDuration()
        : ClusterCommand("pause-action-with-duration")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterPauseActionWithDurationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        params.duration = [NSNumber numberWithUnsignedInt:mRequest.duration];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster pauseActionWithDurationWithParams:params
                                            completion:^(NSError * _Nullable error) {
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::PauseActionWithDuration::Type mRequest;
};

/*
 * Command ResumeAction
 */
class ActionsResumeAction : public ClusterCommand {
public:
    ActionsResumeAction()
        : ClusterCommand("resume-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterResumeActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster resumeActionWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::ResumeAction::Type mRequest;
};

/*
 * Command EnableAction
 */
class ActionsEnableAction : public ClusterCommand {
public:
    ActionsEnableAction()
        : ClusterCommand("enable-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterEnableActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enableActionWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::EnableAction::Type mRequest;
};

/*
 * Command EnableActionWithDuration
 */
class ActionsEnableActionWithDuration : public ClusterCommand {
public:
    ActionsEnableActionWithDuration()
        : ClusterCommand("enable-action-with-duration")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterEnableActionWithDurationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        params.duration = [NSNumber numberWithUnsignedInt:mRequest.duration];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enableActionWithDurationWithParams:params
                                             completion:^(NSError * _Nullable error) {
                                                 responsesNeeded--;
                                                 if (error != nil) {
                                                     mError = error;
                                                     LogNSError("Error", error);
                                                 }
                                                 if (responsesNeeded == 0) {
                                                     SetCommandExitStatus(mError);
                                                 }
                                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::EnableActionWithDuration::Type mRequest;
};

/*
 * Command DisableAction
 */
class ActionsDisableAction : public ClusterCommand {
public:
    ActionsDisableAction()
        : ClusterCommand("disable-action")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterDisableActionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster disableActionWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::DisableAction::Type mRequest;
};

/*
 * Command DisableActionWithDuration
 */
class ActionsDisableActionWithDuration : public ClusterCommand {
public:
    ActionsDisableActionWithDuration()
        : ClusterCommand("disable-action-with-duration")
    {
        AddArgument("ActionID", 0, UINT16_MAX, &mRequest.actionID);
        AddArgument("InvokeID", 0, UINT32_MAX, &mRequest.invokeID);
        AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRActionsClusterDisableActionWithDurationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.actionID = [NSNumber numberWithUnsignedShort:mRequest.actionID];
        if (mRequest.invokeID.HasValue()) {
            params.invokeID = [NSNumber numberWithUnsignedInt:mRequest.invokeID.Value()];
        } else {
            params.invokeID = nil;
        }
        params.duration = [NSNumber numberWithUnsignedInt:mRequest.duration];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster disableActionWithDurationWithParams:params
                                              completion:^(NSError * _Nullable error) {
                                                  responsesNeeded--;
                                                  if (error != nil) {
                                                      mError = error;
                                                      LogNSError("Error", error);
                                                  }
                                                  if (responsesNeeded == 0) {
                                                      SetCommandExitStatus(mError);
                                                  }
                                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Actions::Commands::DisableActionWithDuration::Type mRequest;
};

/*
 * Attribute ActionList
 */
class ReadActionsActionList : public ReadAttribute {
public:
    ReadActionsActionList()
        : ReadAttribute("action-list")
    {
    }

    ~ReadActionsActionList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeActionListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.ActionList response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions ActionList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsActionList : public SubscribeAttribute {
public:
    SubscribeAttributeActionsActionList()
        : SubscribeAttribute("action-list")
    {
    }

    ~SubscribeAttributeActionsActionList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActionListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.ActionList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EndpointLists
 */
class ReadActionsEndpointLists : public ReadAttribute {
public:
    ReadActionsEndpointLists()
        : ReadAttribute("endpoint-lists")
    {
    }

    ~ReadActionsEndpointLists() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeEndpointListsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.EndpointLists response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions EndpointLists read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsEndpointLists : public SubscribeAttribute {
public:
    SubscribeAttributeActionsEndpointLists()
        : SubscribeAttribute("endpoint-lists")
    {
    }

    ~SubscribeAttributeActionsEndpointLists() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEndpointListsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.EndpointLists response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetupURL
 */
class ReadActionsSetupURL : public ReadAttribute {
public:
    ReadActionsSetupURL()
        : ReadAttribute("setup-url")
    {
    }

    ~ReadActionsSetupURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeSetupURLWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.SetupURL response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions SetupURL read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsSetupURL : public SubscribeAttribute {
public:
    SubscribeAttributeActionsSetupURL()
        : SubscribeAttribute("setup-url")
    {
    }

    ~SubscribeAttributeActionsSetupURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSetupURLWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.SetupURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadActionsGeneratedCommandList : public ReadAttribute {
public:
    ReadActionsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadActionsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeActionsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeActionsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadActionsAcceptedCommandList : public ReadAttribute {
public:
    ReadActionsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadActionsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeActionsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeActionsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadActionsAttributeList : public ReadAttribute {
public:
    ReadActionsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadActionsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeActionsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeActionsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadActionsFeatureMap : public ReadAttribute {
public:
    ReadActionsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadActionsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeActionsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeActionsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadActionsClusterRevision : public ReadAttribute {
public:
    ReadActionsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadActionsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Actions.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Actions ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeActionsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeActionsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeActionsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000025) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterActions * cluster = [[MTRBaseClusterActions alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Actions.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Basic                                                       | 0x0028 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * MfgSpecificPing                                                   |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * DataModelRevision                                                 | 0x0000 |
| * VendorName                                                        | 0x0001 |
| * VendorID                                                          | 0x0002 |
| * ProductName                                                       | 0x0003 |
| * ProductID                                                         | 0x0004 |
| * NodeLabel                                                         | 0x0005 |
| * Location                                                          | 0x0006 |
| * HardwareVersion                                                   | 0x0007 |
| * HardwareVersionString                                             | 0x0008 |
| * SoftwareVersion                                                   | 0x0009 |
| * SoftwareVersionString                                             | 0x000A |
| * ManufacturingDate                                                 | 0x000B |
| * PartNumber                                                        | 0x000C |
| * ProductURL                                                        | 0x000D |
| * ProductLabel                                                      | 0x000E |
| * SerialNumber                                                      | 0x000F |
| * LocalConfigDisabled                                               | 0x0010 |
| * Reachable                                                         | 0x0011 |
| * UniqueID                                                          | 0x0012 |
| * CapabilityMinima                                                  | 0x0013 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StartUp                                                           | 0x0000 |
| * ShutDown                                                          | 0x0001 |
| * Leave                                                             | 0x0002 |
| * ReachableChanged                                                  | 0x0003 |
\*----------------------------------------------------------------------------*/

/*
 * Command MfgSpecificPing
 */
class BasicMfgSpecificPing : public ClusterCommand {
public:
    BasicMfgSpecificPing()
        : ClusterCommand("mfg-specific-ping")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRBasicClusterMfgSpecificPingParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster mfgSpecificPingWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute DataModelRevision
 */
class ReadBasicDataModelRevision : public ReadAttribute {
public:
    ReadBasicDataModelRevision()
        : ReadAttribute("data-model-revision")
    {
    }

    ~ReadBasicDataModelRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeDataModelRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.DataModelRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic DataModelRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicDataModelRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBasicDataModelRevision()
        : SubscribeAttribute("data-model-revision")
    {
    }

    ~SubscribeAttributeBasicDataModelRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDataModelRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.DataModelRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorName
 */
class ReadBasicVendorName : public ReadAttribute {
public:
    ReadBasicVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeBasicVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadBasicVendorID : public ReadAttribute {
public:
    ReadBasicVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeBasicVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductName
 */
class ReadBasicProductName : public ReadAttribute {
public:
    ReadBasicProductName()
        : ReadAttribute("product-name")
    {
    }

    ~ReadBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeProductNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ProductName response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ProductName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicProductName : public SubscribeAttribute {
public:
    SubscribeAttributeBasicProductName()
        : SubscribeAttribute("product-name")
    {
    }

    ~SubscribeAttributeBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductID
 */
class ReadBasicProductID : public ReadAttribute {
public:
    ReadBasicProductID()
        : ReadAttribute("product-id")
    {
    }

    ~ReadBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeProductIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ProductID response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ProductID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicProductID : public SubscribeAttribute {
public:
    SubscribeAttributeBasicProductID()
        : SubscribeAttribute("product-id")
    {
    }

    ~SubscribeAttributeBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NodeLabel
 */
class ReadBasicNodeLabel : public ReadAttribute {
public:
    ReadBasicNodeLabel()
        : ReadAttribute("node-label")
    {
    }

    ~ReadBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeNodeLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.NodeLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic NodeLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBasicNodeLabel : public WriteAttribute {
public:
    WriteBasicNodeLabel()
        : WriteAttribute("node-label")
    {
        AddArgument("attr-name", "node-label");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeNodeLabelWithValue:value
                                           params:params
                                       completion:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("Basic NodeLabel write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBasicNodeLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBasicNodeLabel()
        : SubscribeAttribute("node-label")
    {
    }

    ~SubscribeAttributeBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNodeLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.NodeLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Location
 */
class ReadBasicLocation : public ReadAttribute {
public:
    ReadBasicLocation()
        : ReadAttribute("location")
    {
    }

    ~ReadBasicLocation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeLocationWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.Location response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic Location read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBasicLocation : public WriteAttribute {
public:
    WriteBasicLocation()
        : WriteAttribute("location")
    {
        AddArgument("attr-name", "location");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBasicLocation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLocationWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("Basic Location write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBasicLocation : public SubscribeAttribute {
public:
    SubscribeAttributeBasicLocation()
        : SubscribeAttribute("location")
    {
    }

    ~SubscribeAttributeBasicLocation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLocationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.Location response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersion
 */
class ReadBasicHardwareVersion : public ReadAttribute {
public:
    ReadBasicHardwareVersion()
        : ReadAttribute("hardware-version")
    {
    }

    ~ReadBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeHardwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.HardwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic HardwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicHardwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBasicHardwareVersion()
        : SubscribeAttribute("hardware-version")
    {
    }

    ~SubscribeAttributeBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHardwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.HardwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersionString
 */
class ReadBasicHardwareVersionString : public ReadAttribute {
public:
    ReadBasicHardwareVersionString()
        : ReadAttribute("hardware-version-string")
    {
    }

    ~ReadBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeHardwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.HardwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic HardwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicHardwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBasicHardwareVersionString()
        : SubscribeAttribute("hardware-version-string")
    {
    }

    ~SubscribeAttributeBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHardwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.HardwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersion
 */
class ReadBasicSoftwareVersion : public ReadAttribute {
public:
    ReadBasicSoftwareVersion()
        : ReadAttribute("software-version")
    {
    }

    ~ReadBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeSoftwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.SoftwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic SoftwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicSoftwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBasicSoftwareVersion()
        : SubscribeAttribute("software-version")
    {
    }

    ~SubscribeAttributeBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSoftwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.SoftwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersionString
 */
class ReadBasicSoftwareVersionString : public ReadAttribute {
public:
    ReadBasicSoftwareVersionString()
        : ReadAttribute("software-version-string")
    {
    }

    ~ReadBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeSoftwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.SoftwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic SoftwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicSoftwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBasicSoftwareVersionString()
        : SubscribeAttribute("software-version-string")
    {
    }

    ~SubscribeAttributeBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSoftwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.SoftwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ManufacturingDate
 */
class ReadBasicManufacturingDate : public ReadAttribute {
public:
    ReadBasicManufacturingDate()
        : ReadAttribute("manufacturing-date")
    {
    }

    ~ReadBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeManufacturingDateWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ManufacturingDate response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ManufacturingDate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicManufacturingDate : public SubscribeAttribute {
public:
    SubscribeAttributeBasicManufacturingDate()
        : SubscribeAttribute("manufacturing-date")
    {
    }

    ~SubscribeAttributeBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeManufacturingDateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ManufacturingDate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartNumber
 */
class ReadBasicPartNumber : public ReadAttribute {
public:
    ReadBasicPartNumber()
        : ReadAttribute("part-number")
    {
    }

    ~ReadBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributePartNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.PartNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic PartNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicPartNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBasicPartNumber()
        : SubscribeAttribute("part-number")
    {
    }

    ~SubscribeAttributeBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePartNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.PartNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductURL
 */
class ReadBasicProductURL : public ReadAttribute {
public:
    ReadBasicProductURL()
        : ReadAttribute("product-url")
    {
    }

    ~ReadBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeProductURLWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ProductURL response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ProductURL read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicProductURL : public SubscribeAttribute {
public:
    SubscribeAttributeBasicProductURL()
        : SubscribeAttribute("product-url")
    {
    }

    ~SubscribeAttributeBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductURLWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductLabel
 */
class ReadBasicProductLabel : public ReadAttribute {
public:
    ReadBasicProductLabel()
        : ReadAttribute("product-label")
    {
    }

    ~ReadBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeProductLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ProductLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ProductLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicProductLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBasicProductLabel()
        : SubscribeAttribute("product-label")
    {
    }

    ~SubscribeAttributeBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ProductLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SerialNumber
 */
class ReadBasicSerialNumber : public ReadAttribute {
public:
    ReadBasicSerialNumber()
        : ReadAttribute("serial-number")
    {
    }

    ~ReadBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeSerialNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.SerialNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic SerialNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicSerialNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBasicSerialNumber()
        : SubscribeAttribute("serial-number")
    {
    }

    ~SubscribeAttributeBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSerialNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.SerialNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocalConfigDisabled
 */
class ReadBasicLocalConfigDisabled : public ReadAttribute {
public:
    ReadBasicLocalConfigDisabled()
        : ReadAttribute("local-config-disabled")
    {
    }

    ~ReadBasicLocalConfigDisabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeLocalConfigDisabledWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.LocalConfigDisabled response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic LocalConfigDisabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBasicLocalConfigDisabled : public WriteAttribute {
public:
    WriteBasicLocalConfigDisabled()
        : WriteAttribute("local-config-disabled")
    {
        AddArgument("attr-name", "local-config-disabled");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBasicLocalConfigDisabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeLocalConfigDisabledWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("Basic LocalConfigDisabled write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeBasicLocalConfigDisabled : public SubscribeAttribute {
public:
    SubscribeAttributeBasicLocalConfigDisabled()
        : SubscribeAttribute("local-config-disabled")
    {
    }

    ~SubscribeAttributeBasicLocalConfigDisabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLocalConfigDisabledWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.LocalConfigDisabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Reachable
 */
class ReadBasicReachable : public ReadAttribute {
public:
    ReadBasicReachable()
        : ReadAttribute("reachable")
    {
    }

    ~ReadBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeReachableWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.Reachable response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic Reachable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicReachable : public SubscribeAttribute {
public:
    SubscribeAttributeBasicReachable()
        : SubscribeAttribute("reachable")
    {
    }

    ~SubscribeAttributeBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReachableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.Reachable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UniqueID
 */
class ReadBasicUniqueID : public ReadAttribute {
public:
    ReadBasicUniqueID()
        : ReadAttribute("unique-id")
    {
    }

    ~ReadBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeUniqueIDWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.UniqueID response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic UniqueID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicUniqueID : public SubscribeAttribute {
public:
    SubscribeAttributeBasicUniqueID()
        : SubscribeAttribute("unique-id")
    {
    }

    ~SubscribeAttributeBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUniqueIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.UniqueID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CapabilityMinima
 */
class ReadBasicCapabilityMinima : public ReadAttribute {
public:
    ReadBasicCapabilityMinima()
        : ReadAttribute("capability-minima")
    {
    }

    ~ReadBasicCapabilityMinima() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeCapabilityMinimaWithCompletion:^(
            MTRBasicClusterCapabilityMinimaStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.CapabilityMinima response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic CapabilityMinima read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicCapabilityMinima : public SubscribeAttribute {
public:
    SubscribeAttributeBasicCapabilityMinima()
        : SubscribeAttribute("capability-minima")
    {
    }

    ~SubscribeAttributeBasicCapabilityMinima() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCapabilityMinimaWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRBasicClusterCapabilityMinimaStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.CapabilityMinima response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBasicGeneratedCommandList : public ReadAttribute {
public:
    ReadBasicGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBasicGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBasicAcceptedCommandList : public ReadAttribute {
public:
    ReadBasicAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBasicAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBasicAttributeList : public ReadAttribute {
public:
    ReadBasicAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBasicAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBasicFeatureMap : public ReadAttribute {
public:
    ReadBasicFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBasicFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBasicClusterRevision : public ReadAttribute {
public:
    ReadBasicClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Basic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Basic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000028) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBasic * cluster = [[MTRBaseClusterBasic alloc] initWithDevice:device
                                                                         endpointID:@(endpointId)
                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Basic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OtaSoftwareUpdateProvider                                   | 0x0029 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * QueryImage                                                        |   0x00 |
| * ApplyUpdateRequest                                                |   0x02 |
| * NotifyUpdateApplied                                               |   0x04 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command QueryImage
 */
class OtaSoftwareUpdateProviderQueryImage : public ClusterCommand {
public:
    OtaSoftwareUpdateProviderQueryImage()
        : ClusterCommand("query-image")
        , mComplex_ProtocolsSupported(&mRequest.protocolsSupported)
    {
        AddArgument("VendorId", 0, UINT16_MAX, &mRequest.vendorId);
        AddArgument("ProductId", 0, UINT16_MAX, &mRequest.productId);
        AddArgument("SoftwareVersion", 0, UINT32_MAX, &mRequest.softwareVersion);
        AddArgument("ProtocolsSupported", &mComplex_ProtocolsSupported);
        AddArgument("HardwareVersion", 0, UINT16_MAX, &mRequest.hardwareVersion);
        AddArgument("Location", &mRequest.location);
        AddArgument("RequestorCanConsent", 0, 1, &mRequest.requestorCanConsent);
        AddArgument("MetadataForProvider", &mRequest.metadataForProvider);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROtaSoftwareUpdateProviderClusterQueryImageParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.vendorId = [NSNumber numberWithUnsignedShort:chip::to_underlying(mRequest.vendorId)];
        params.productId = [NSNumber numberWithUnsignedShort:mRequest.productId];
        params.softwareVersion = [NSNumber numberWithUnsignedInt:mRequest.softwareVersion];
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.protocolsSupported) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0)];
                [array_0 addObject:newElement_0];
            }
            params.protocolsSupported = array_0;
        }
        if (mRequest.hardwareVersion.HasValue()) {
            params.hardwareVersion = [NSNumber numberWithUnsignedShort:mRequest.hardwareVersion.Value()];
        } else {
            params.hardwareVersion = nil;
        }
        if (mRequest.location.HasValue()) {
            params.location = [[NSString alloc] initWithBytes:mRequest.location.Value().data()
                                                       length:mRequest.location.Value().size()
                                                     encoding:NSUTF8StringEncoding];
        } else {
            params.location = nil;
        }
        if (mRequest.requestorCanConsent.HasValue()) {
            params.requestorCanConsent = [NSNumber numberWithBool:mRequest.requestorCanConsent.Value()];
        } else {
            params.requestorCanConsent = nil;
        }
        if (mRequest.metadataForProvider.HasValue()) {
            params.metadataForProvider = [NSData dataWithBytes:mRequest.metadataForProvider.Value().data()
                                                        length:mRequest.metadataForProvider.Value().size()];
        } else {
            params.metadataForProvider = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster queryImageWithParams:params
                               completion:^(MTROtaSoftwareUpdateProviderClusterQueryImageResponseParams * _Nullable values,
                                   NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::QueryImage::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::OtaSoftwareUpdateProvider::OTADownloadProtocol>>
        mComplex_ProtocolsSupported;
};

/*
 * Command ApplyUpdateRequest
 */
class OtaSoftwareUpdateProviderApplyUpdateRequest : public ClusterCommand {
public:
    OtaSoftwareUpdateProviderApplyUpdateRequest()
        : ClusterCommand("apply-update-request")
    {
        AddArgument("UpdateToken", &mRequest.updateToken);
        AddArgument("NewVersion", 0, UINT32_MAX, &mRequest.newVersion);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROtaSoftwareUpdateProviderClusterApplyUpdateRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.updateToken = [NSData dataWithBytes:mRequest.updateToken.data() length:mRequest.updateToken.size()];
        params.newVersion = [NSNumber numberWithUnsignedInt:mRequest.newVersion];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster applyUpdateRequestWithParams:params
                                       completion:^(MTROtaSoftwareUpdateProviderClusterApplyUpdateResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::ApplyUpdateRequest::Type mRequest;
};

/*
 * Command NotifyUpdateApplied
 */
class OtaSoftwareUpdateProviderNotifyUpdateApplied : public ClusterCommand {
public:
    OtaSoftwareUpdateProviderNotifyUpdateApplied()
        : ClusterCommand("notify-update-applied")
    {
        AddArgument("UpdateToken", &mRequest.updateToken);
        AddArgument("SoftwareVersion", 0, UINT32_MAX, &mRequest.softwareVersion);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROtaSoftwareUpdateProviderClusterNotifyUpdateAppliedParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.updateToken = [NSData dataWithBytes:mRequest.updateToken.data() length:mRequest.updateToken.size()];
        params.softwareVersion = [NSNumber numberWithUnsignedInt:mRequest.softwareVersion];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster notifyUpdateAppliedWithParams:params
                                        completion:^(NSError * _Nullable error) {
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateProvider::Commands::NotifyUpdateApplied::Type mRequest;
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOtaSoftwareUpdateProviderGeneratedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOtaSoftwareUpdateProviderAcceptedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOtaSoftwareUpdateProviderAttributeList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOtaSoftwareUpdateProviderAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOtaSoftwareUpdateProviderFeatureMap : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOtaSoftwareUpdateProviderFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOtaSoftwareUpdateProviderClusterRevision : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateProviderClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOtaSoftwareUpdateProviderClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateProvider.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateProvider ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000029) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateProvider * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateProvider alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateProvider.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OtaSoftwareUpdateRequestor                                  | 0x002A |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * AnnounceOtaProvider                                               |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * DefaultOtaProviders                                               | 0x0000 |
| * UpdatePossible                                                    | 0x0001 |
| * UpdateState                                                       | 0x0002 |
| * UpdateStateProgress                                               | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateTransition                                                   | 0x0000 |
| * VersionApplied                                                    | 0x0001 |
| * DownloadError                                                     | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command AnnounceOtaProvider
 */
class OtaSoftwareUpdateRequestorAnnounceOtaProvider : public ClusterCommand {
public:
    OtaSoftwareUpdateRequestorAnnounceOtaProvider()
        : ClusterCommand("announce-ota-provider")
    {
        AddArgument("ProviderNodeId", 0, UINT64_MAX, &mRequest.providerNodeId);
        AddArgument("VendorId", 0, UINT16_MAX, &mRequest.vendorId);
        AddArgument("AnnouncementReason", 0, UINT8_MAX, &mRequest.announcementReason);
        AddArgument("MetadataForNode", &mRequest.metadataForNode);
        AddArgument("Endpoint", 0, UINT16_MAX, &mRequest.endpoint);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROtaSoftwareUpdateRequestorClusterAnnounceOtaProviderParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.providerNodeId = [NSNumber numberWithUnsignedLongLong:mRequest.providerNodeId];
        params.vendorId = [NSNumber numberWithUnsignedShort:chip::to_underlying(mRequest.vendorId)];
        params.announcementReason = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.announcementReason)];
        if (mRequest.metadataForNode.HasValue()) {
            params.metadataForNode = [NSData dataWithBytes:mRequest.metadataForNode.Value().data()
                                                    length:mRequest.metadataForNode.Value().size()];
        } else {
            params.metadataForNode = nil;
        }
        params.endpoint = [NSNumber numberWithUnsignedShort:mRequest.endpoint];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster announceOtaProviderWithParams:params
                                        completion:^(NSError * _Nullable error) {
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOtaProvider::Type mRequest;
};

/*
 * Attribute DefaultOtaProviders
 */
class ReadOtaSoftwareUpdateRequestorDefaultOtaProviders : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorDefaultOtaProviders()
        : ReadAttribute("default-ota-providers")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorDefaultOtaProviders() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster
            readAttributeDefaultOtaProvidersWithParams:params
                                            completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                                NSLog(@"OtaSoftwareUpdateRequestor.DefaultOtaProviders response %@",
                                                    [value description]);
                                                if (error != nil) {
                                                    LogNSError("OtaSoftwareUpdateRequestor DefaultOtaProviders read Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }
};

class WriteOtaSoftwareUpdateRequestorDefaultOtaProviders : public WriteAttribute {
public:
    WriteOtaSoftwareUpdateRequestorDefaultOtaProviders()
        : WriteAttribute("default-ota-providers")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "default-ota-providers");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteOtaSoftwareUpdateRequestorDefaultOtaProviders() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * 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) {
                MTROtaSoftwareUpdateRequestorClusterProviderLocation * newElement_0;
                newElement_0 = [MTROtaSoftwareUpdateRequestorClusterProviderLocation new];
                newElement_0.providerNodeID = [NSNumber numberWithUnsignedLongLong:entry_0.providerNodeID];
                newElement_0.endpoint = [NSNumber numberWithUnsignedShort:entry_0.endpoint];
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster
            writeAttributeDefaultOtaProvidersWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("OtaSoftwareUpdateRequestor DefaultOtaProviders write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::OtaSoftwareUpdateRequestor::Structs::ProviderLocation::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::OtaSoftwareUpdateRequestor::Structs::ProviderLocation::Type>>
        mComplex;
};

class SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders()
        : SubscribeAttribute("default-ota-providers")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDefaultOtaProvidersWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.DefaultOtaProviders response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpdatePossible
 */
class ReadOtaSoftwareUpdateRequestorUpdatePossible : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorUpdatePossible()
        : ReadAttribute("update-possible")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorUpdatePossible() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeUpdatePossibleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.UpdatePossible response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor UpdatePossible read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible()
        : SubscribeAttribute("update-possible")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUpdatePossibleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.UpdatePossible response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpdateState
 */
class ReadOtaSoftwareUpdateRequestorUpdateState : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorUpdateState()
        : ReadAttribute("update-state")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorUpdateState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeUpdateStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.UpdateState response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor UpdateState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState()
        : SubscribeAttribute("update-state")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUpdateStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.UpdateState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpdateStateProgress
 */
class ReadOtaSoftwareUpdateRequestorUpdateStateProgress : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorUpdateStateProgress()
        : ReadAttribute("update-state-progress")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorUpdateStateProgress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeUpdateStateProgressWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.UpdateStateProgress response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor UpdateStateProgress read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress()
        : SubscribeAttribute("update-state-progress")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUpdateStateProgressWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.UpdateStateProgress response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOtaSoftwareUpdateRequestorGeneratedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOtaSoftwareUpdateRequestorAcceptedCommandList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOtaSoftwareUpdateRequestorAttributeList : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOtaSoftwareUpdateRequestorFeatureMap : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOtaSoftwareUpdateRequestorClusterRevision : public ReadAttribute {
public:
    ReadOtaSoftwareUpdateRequestorClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOtaSoftwareUpdateRequestorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OtaSoftwareUpdateRequestor.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OtaSoftwareUpdateRequestor ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002A) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOtaSoftwareUpdateRequestor * cluster =
            [[MTRBaseClusterOtaSoftwareUpdateRequestor alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OtaSoftwareUpdateRequestor.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster LocalizationConfiguration                                   | 0x002B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ActiveLocale                                                      | 0x0000 |
| * SupportedLocales                                                  | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute ActiveLocale
 */
class ReadLocalizationConfigurationActiveLocale : public ReadAttribute {
public:
    ReadLocalizationConfigurationActiveLocale()
        : ReadAttribute("active-locale")
    {
    }

    ~ReadLocalizationConfigurationActiveLocale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeActiveLocaleWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.ActiveLocale response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration ActiveLocale read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteLocalizationConfigurationActiveLocale : public WriteAttribute {
public:
    WriteLocalizationConfigurationActiveLocale()
        : WriteAttribute("active-locale")
    {
        AddArgument("attr-name", "active-locale");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteLocalizationConfigurationActiveLocale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeActiveLocaleWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("LocalizationConfiguration ActiveLocale write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeLocalizationConfigurationActiveLocale : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationActiveLocale()
        : SubscribeAttribute("active-locale")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationActiveLocale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveLocaleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.ActiveLocale response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedLocales
 */
class ReadLocalizationConfigurationSupportedLocales : public ReadAttribute {
public:
    ReadLocalizationConfigurationSupportedLocales()
        : ReadAttribute("supported-locales")
    {
    }

    ~ReadLocalizationConfigurationSupportedLocales() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSupportedLocalesWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.SupportedLocales response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration SupportedLocales read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationSupportedLocales : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationSupportedLocales()
        : SubscribeAttribute("supported-locales")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationSupportedLocales() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportedLocalesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.SupportedLocales response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadLocalizationConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadLocalizationConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadLocalizationConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadLocalizationConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadLocalizationConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadLocalizationConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadLocalizationConfigurationAttributeList : public ReadAttribute {
public:
    ReadLocalizationConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadLocalizationConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadLocalizationConfigurationFeatureMap : public ReadAttribute {
public:
    ReadLocalizationConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadLocalizationConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadLocalizationConfigurationClusterRevision : public ReadAttribute {
public:
    ReadLocalizationConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadLocalizationConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LocalizationConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("LocalizationConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLocalizationConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeLocalizationConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeLocalizationConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002B) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLocalizationConfiguration * cluster =
            [[MTRBaseClusterLocalizationConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LocalizationConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TimeFormatLocalization                                      | 0x002C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * HourFormat                                                        | 0x0000 |
| * ActiveCalendarType                                                | 0x0001 |
| * SupportedCalendarTypes                                            | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute HourFormat
 */
class ReadTimeFormatLocalizationHourFormat : public ReadAttribute {
public:
    ReadTimeFormatLocalizationHourFormat()
        : ReadAttribute("hour-format")
    {
    }

    ~ReadTimeFormatLocalizationHourFormat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeHourFormatWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.HourFormat response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization HourFormat read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTimeFormatLocalizationHourFormat : public WriteAttribute {
public:
    WriteTimeFormatLocalizationHourFormat()
        : WriteAttribute("hour-format")
    {
        AddArgument("attr-name", "hour-format");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTimeFormatLocalizationHourFormat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeHourFormatWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("TimeFormatLocalization HourFormat write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTimeFormatLocalizationHourFormat : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationHourFormat()
        : SubscribeAttribute("hour-format")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationHourFormat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHourFormatWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.HourFormat response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveCalendarType
 */
class ReadTimeFormatLocalizationActiveCalendarType : public ReadAttribute {
public:
    ReadTimeFormatLocalizationActiveCalendarType()
        : ReadAttribute("active-calendar-type")
    {
    }

    ~ReadTimeFormatLocalizationActiveCalendarType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeActiveCalendarTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.ActiveCalendarType response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization ActiveCalendarType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTimeFormatLocalizationActiveCalendarType : public WriteAttribute {
public:
    WriteTimeFormatLocalizationActiveCalendarType()
        : WriteAttribute("active-calendar-type")
    {
        AddArgument("attr-name", "active-calendar-type");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTimeFormatLocalizationActiveCalendarType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeActiveCalendarTypeWithValue:value
                                                    params:params
                                                completion:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("TimeFormatLocalization ActiveCalendarType write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTimeFormatLocalizationActiveCalendarType : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationActiveCalendarType()
        : SubscribeAttribute("active-calendar-type")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationActiveCalendarType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveCalendarTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.ActiveCalendarType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedCalendarTypes
 */
class ReadTimeFormatLocalizationSupportedCalendarTypes : public ReadAttribute {
public:
    ReadTimeFormatLocalizationSupportedCalendarTypes()
        : ReadAttribute("supported-calendar-types")
    {
    }

    ~ReadTimeFormatLocalizationSupportedCalendarTypes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSupportedCalendarTypesWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.SupportedCalendarTypes response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization SupportedCalendarTypes read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes()
        : SubscribeAttribute("supported-calendar-types")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportedCalendarTypesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.SupportedCalendarTypes response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTimeFormatLocalizationGeneratedCommandList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTimeFormatLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTimeFormatLocalizationAcceptedCommandList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTimeFormatLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTimeFormatLocalizationAttributeList : public ReadAttribute {
public:
    ReadTimeFormatLocalizationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTimeFormatLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTimeFormatLocalizationFeatureMap : public ReadAttribute {
public:
    ReadTimeFormatLocalizationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTimeFormatLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTimeFormatLocalizationClusterRevision : public ReadAttribute {
public:
    ReadTimeFormatLocalizationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTimeFormatLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TimeFormatLocalization.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TimeFormatLocalization ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTimeFormatLocalizationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTimeFormatLocalizationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTimeFormatLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTimeFormatLocalization * cluster =
            [[MTRBaseClusterTimeFormatLocalization alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TimeFormatLocalization.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster UnitLocalization                                            | 0x002D |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TemperatureUnit                                                   | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute TemperatureUnit
 */
class ReadUnitLocalizationTemperatureUnit : public ReadAttribute {
public:
    ReadUnitLocalizationTemperatureUnit()
        : ReadAttribute("temperature-unit")
    {
    }

    ~ReadUnitLocalizationTemperatureUnit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeTemperatureUnitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.TemperatureUnit response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization TemperatureUnit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUnitLocalizationTemperatureUnit : public WriteAttribute {
public:
    WriteUnitLocalizationTemperatureUnit()
        : WriteAttribute("temperature-unit")
    {
        AddArgument("attr-name", "temperature-unit");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteUnitLocalizationTemperatureUnit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeTemperatureUnitWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("UnitLocalization TemperatureUnit write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeUnitLocalizationTemperatureUnit : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationTemperatureUnit()
        : SubscribeAttribute("temperature-unit")
    {
    }

    ~SubscribeAttributeUnitLocalizationTemperatureUnit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTemperatureUnitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.TemperatureUnit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadUnitLocalizationGeneratedCommandList : public ReadAttribute {
public:
    ReadUnitLocalizationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadUnitLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadUnitLocalizationAcceptedCommandList : public ReadAttribute {
public:
    ReadUnitLocalizationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadUnitLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadUnitLocalizationAttributeList : public ReadAttribute {
public:
    ReadUnitLocalizationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadUnitLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeUnitLocalizationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadUnitLocalizationFeatureMap : public ReadAttribute {
public:
    ReadUnitLocalizationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadUnitLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeUnitLocalizationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadUnitLocalizationClusterRevision : public ReadAttribute {
public:
    ReadUnitLocalizationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadUnitLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UnitLocalization.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("UnitLocalization ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUnitLocalizationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeUnitLocalizationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeUnitLocalizationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002D) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUnitLocalization * cluster = [[MTRBaseClusterUnitLocalization alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UnitLocalization.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PowerSourceConfiguration                                    | 0x002E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Sources                                                           | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Sources
 */
class ReadPowerSourceConfigurationSources : public ReadAttribute {
public:
    ReadPowerSourceConfigurationSources()
        : ReadAttribute("sources")
    {
    }

    ~ReadPowerSourceConfigurationSources() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSourcesWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.Sources response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration Sources read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationSources : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationSources()
        : SubscribeAttribute("sources")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationSources() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSourcesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.Sources response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPowerSourceConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPowerSourceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPowerSourceConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPowerSourceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPowerSourceConfigurationAttributeList : public ReadAttribute {
public:
    ReadPowerSourceConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPowerSourceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPowerSourceConfigurationFeatureMap : public ReadAttribute {
public:
    ReadPowerSourceConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPowerSourceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPowerSourceConfigurationClusterRevision : public ReadAttribute {
public:
    ReadPowerSourceConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPowerSourceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSourceConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSourceConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePowerSourceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSourceConfiguration * cluster =
            [[MTRBaseClusterPowerSourceConfiguration alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSourceConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PowerSource                                                 | 0x002F |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Status                                                            | 0x0000 |
| * Order                                                             | 0x0001 |
| * Description                                                       | 0x0002 |
| * WiredAssessedInputVoltage                                         | 0x0003 |
| * WiredAssessedInputFrequency                                       | 0x0004 |
| * WiredCurrentType                                                  | 0x0005 |
| * WiredAssessedCurrent                                              | 0x0006 |
| * WiredNominalVoltage                                               | 0x0007 |
| * WiredMaximumCurrent                                               | 0x0008 |
| * WiredPresent                                                      | 0x0009 |
| * ActiveWiredFaults                                                 | 0x000A |
| * BatVoltage                                                        | 0x000B |
| * BatPercentRemaining                                               | 0x000C |
| * BatTimeRemaining                                                  | 0x000D |
| * BatChargeLevel                                                    | 0x000E |
| * BatReplacementNeeded                                              | 0x000F |
| * BatReplaceability                                                 | 0x0010 |
| * BatPresent                                                        | 0x0011 |
| * ActiveBatFaults                                                   | 0x0012 |
| * BatReplacementDescription                                         | 0x0013 |
| * BatCommonDesignation                                              | 0x0014 |
| * BatANSIDesignation                                                | 0x0015 |
| * BatIECDesignation                                                 | 0x0016 |
| * BatApprovedChemistry                                              | 0x0017 |
| * BatCapacity                                                       | 0x0018 |
| * BatQuantity                                                       | 0x0019 |
| * BatChargeState                                                    | 0x001A |
| * BatTimeToFullCharge                                               | 0x001B |
| * BatFunctionalWhileCharging                                        | 0x001C |
| * BatChargingCurrent                                                | 0x001D |
| * ActiveBatChargeFaults                                             | 0x001E |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Status
 */
class ReadPowerSourceStatus : public ReadAttribute {
public:
    ReadPowerSourceStatus()
        : ReadAttribute("status")
    {
    }

    ~ReadPowerSourceStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.Status response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource Status read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceStatus : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceStatus()
        : SubscribeAttribute("status")
    {
    }

    ~SubscribeAttributePowerSourceStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.Status response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Order
 */
class ReadPowerSourceOrder : public ReadAttribute {
public:
    ReadPowerSourceOrder()
        : ReadAttribute("order")
    {
    }

    ~ReadPowerSourceOrder() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeOrderWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.Order response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource Order read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceOrder : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceOrder()
        : SubscribeAttribute("order")
    {
    }

    ~SubscribeAttributePowerSourceOrder() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOrderWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.Order response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Description
 */
class ReadPowerSourceDescription : public ReadAttribute {
public:
    ReadPowerSourceDescription()
        : ReadAttribute("description")
    {
    }

    ~ReadPowerSourceDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeDescriptionWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.Description response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource Description read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceDescription : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceDescription()
        : SubscribeAttribute("description")
    {
    }

    ~SubscribeAttributePowerSourceDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDescriptionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.Description response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredAssessedInputVoltage
 */
class ReadPowerSourceWiredAssessedInputVoltage : public ReadAttribute {
public:
    ReadPowerSourceWiredAssessedInputVoltage()
        : ReadAttribute("wired-assessed-input-voltage")
    {
    }

    ~ReadPowerSourceWiredAssessedInputVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredAssessedInputVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredAssessedInputVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredAssessedInputVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredAssessedInputVoltage : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredAssessedInputVoltage()
        : SubscribeAttribute("wired-assessed-input-voltage")
    {
    }

    ~SubscribeAttributePowerSourceWiredAssessedInputVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredAssessedInputVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedInputVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredAssessedInputFrequency
 */
class ReadPowerSourceWiredAssessedInputFrequency : public ReadAttribute {
public:
    ReadPowerSourceWiredAssessedInputFrequency()
        : ReadAttribute("wired-assessed-input-frequency")
    {
    }

    ~ReadPowerSourceWiredAssessedInputFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredAssessedInputFrequencyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredAssessedInputFrequency response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredAssessedInputFrequency read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredAssessedInputFrequency : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredAssessedInputFrequency()
        : SubscribeAttribute("wired-assessed-input-frequency")
    {
    }

    ~SubscribeAttributePowerSourceWiredAssessedInputFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredAssessedInputFrequencyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedInputFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredCurrentType
 */
class ReadPowerSourceWiredCurrentType : public ReadAttribute {
public:
    ReadPowerSourceWiredCurrentType()
        : ReadAttribute("wired-current-type")
    {
    }

    ~ReadPowerSourceWiredCurrentType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredCurrentTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredCurrentType response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredCurrentType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredCurrentType : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredCurrentType()
        : SubscribeAttribute("wired-current-type")
    {
    }

    ~SubscribeAttributePowerSourceWiredCurrentType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredCurrentTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredCurrentType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredAssessedCurrent
 */
class ReadPowerSourceWiredAssessedCurrent : public ReadAttribute {
public:
    ReadPowerSourceWiredAssessedCurrent()
        : ReadAttribute("wired-assessed-current")
    {
    }

    ~ReadPowerSourceWiredAssessedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredAssessedCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredAssessedCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredAssessedCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredAssessedCurrent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredAssessedCurrent()
        : SubscribeAttribute("wired-assessed-current")
    {
    }

    ~SubscribeAttributePowerSourceWiredAssessedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredAssessedCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredAssessedCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredNominalVoltage
 */
class ReadPowerSourceWiredNominalVoltage : public ReadAttribute {
public:
    ReadPowerSourceWiredNominalVoltage()
        : ReadAttribute("wired-nominal-voltage")
    {
    }

    ~ReadPowerSourceWiredNominalVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredNominalVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredNominalVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredNominalVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredNominalVoltage : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredNominalVoltage()
        : SubscribeAttribute("wired-nominal-voltage")
    {
    }

    ~SubscribeAttributePowerSourceWiredNominalVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredNominalVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredNominalVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredMaximumCurrent
 */
class ReadPowerSourceWiredMaximumCurrent : public ReadAttribute {
public:
    ReadPowerSourceWiredMaximumCurrent()
        : ReadAttribute("wired-maximum-current")
    {
    }

    ~ReadPowerSourceWiredMaximumCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredMaximumCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredMaximumCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredMaximumCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredMaximumCurrent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredMaximumCurrent()
        : SubscribeAttribute("wired-maximum-current")
    {
    }

    ~SubscribeAttributePowerSourceWiredMaximumCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredMaximumCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredMaximumCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiredPresent
 */
class ReadPowerSourceWiredPresent : public ReadAttribute {
public:
    ReadPowerSourceWiredPresent()
        : ReadAttribute("wired-present")
    {
    }

    ~ReadPowerSourceWiredPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWiredPresentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.WiredPresent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource WiredPresent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceWiredPresent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceWiredPresent()
        : SubscribeAttribute("wired-present")
    {
    }

    ~SubscribeAttributePowerSourceWiredPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiredPresentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.WiredPresent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveWiredFaults
 */
class ReadPowerSourceActiveWiredFaults : public ReadAttribute {
public:
    ReadPowerSourceActiveWiredFaults()
        : ReadAttribute("active-wired-faults")
    {
    }

    ~ReadPowerSourceActiveWiredFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeActiveWiredFaultsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ActiveWiredFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ActiveWiredFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceActiveWiredFaults : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceActiveWiredFaults()
        : SubscribeAttribute("active-wired-faults")
    {
    }

    ~SubscribeAttributePowerSourceActiveWiredFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveWiredFaultsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ActiveWiredFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatVoltage
 */
class ReadPowerSourceBatVoltage : public ReadAttribute {
public:
    ReadPowerSourceBatVoltage()
        : ReadAttribute("bat-voltage")
    {
    }

    ~ReadPowerSourceBatVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatVoltage : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatVoltage()
        : SubscribeAttribute("bat-voltage")
    {
    }

    ~SubscribeAttributePowerSourceBatVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatPercentRemaining
 */
class ReadPowerSourceBatPercentRemaining : public ReadAttribute {
public:
    ReadPowerSourceBatPercentRemaining()
        : ReadAttribute("bat-percent-remaining")
    {
    }

    ~ReadPowerSourceBatPercentRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatPercentRemainingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatPercentRemaining response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatPercentRemaining read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatPercentRemaining : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatPercentRemaining()
        : SubscribeAttribute("bat-percent-remaining")
    {
    }

    ~SubscribeAttributePowerSourceBatPercentRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatPercentRemainingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatPercentRemaining response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatTimeRemaining
 */
class ReadPowerSourceBatTimeRemaining : public ReadAttribute {
public:
    ReadPowerSourceBatTimeRemaining()
        : ReadAttribute("bat-time-remaining")
    {
    }

    ~ReadPowerSourceBatTimeRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatTimeRemainingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatTimeRemaining response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatTimeRemaining read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatTimeRemaining : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatTimeRemaining()
        : SubscribeAttribute("bat-time-remaining")
    {
    }

    ~SubscribeAttributePowerSourceBatTimeRemaining() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatTimeRemainingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatTimeRemaining response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatChargeLevel
 */
class ReadPowerSourceBatChargeLevel : public ReadAttribute {
public:
    ReadPowerSourceBatChargeLevel()
        : ReadAttribute("bat-charge-level")
    {
    }

    ~ReadPowerSourceBatChargeLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatChargeLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatChargeLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatChargeLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatChargeLevel : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatChargeLevel()
        : SubscribeAttribute("bat-charge-level")
    {
    }

    ~SubscribeAttributePowerSourceBatChargeLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatChargeLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatChargeLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatReplacementNeeded
 */
class ReadPowerSourceBatReplacementNeeded : public ReadAttribute {
public:
    ReadPowerSourceBatReplacementNeeded()
        : ReadAttribute("bat-replacement-needed")
    {
    }

    ~ReadPowerSourceBatReplacementNeeded() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatReplacementNeededWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatReplacementNeeded response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatReplacementNeeded read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatReplacementNeeded : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatReplacementNeeded()
        : SubscribeAttribute("bat-replacement-needed")
    {
    }

    ~SubscribeAttributePowerSourceBatReplacementNeeded() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatReplacementNeededWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplacementNeeded response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatReplaceability
 */
class ReadPowerSourceBatReplaceability : public ReadAttribute {
public:
    ReadPowerSourceBatReplaceability()
        : ReadAttribute("bat-replaceability")
    {
    }

    ~ReadPowerSourceBatReplaceability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatReplaceabilityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatReplaceability response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatReplaceability read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatReplaceability : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatReplaceability()
        : SubscribeAttribute("bat-replaceability")
    {
    }

    ~SubscribeAttributePowerSourceBatReplaceability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatReplaceabilityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplaceability response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatPresent
 */
class ReadPowerSourceBatPresent : public ReadAttribute {
public:
    ReadPowerSourceBatPresent()
        : ReadAttribute("bat-present")
    {
    }

    ~ReadPowerSourceBatPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatPresentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatPresent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatPresent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatPresent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatPresent()
        : SubscribeAttribute("bat-present")
    {
    }

    ~SubscribeAttributePowerSourceBatPresent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatPresentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatPresent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveBatFaults
 */
class ReadPowerSourceActiveBatFaults : public ReadAttribute {
public:
    ReadPowerSourceActiveBatFaults()
        : ReadAttribute("active-bat-faults")
    {
    }

    ~ReadPowerSourceActiveBatFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeActiveBatFaultsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ActiveBatFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ActiveBatFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceActiveBatFaults : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceActiveBatFaults()
        : SubscribeAttribute("active-bat-faults")
    {
    }

    ~SubscribeAttributePowerSourceActiveBatFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveBatFaultsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ActiveBatFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatReplacementDescription
 */
class ReadPowerSourceBatReplacementDescription : public ReadAttribute {
public:
    ReadPowerSourceBatReplacementDescription()
        : ReadAttribute("bat-replacement-description")
    {
    }

    ~ReadPowerSourceBatReplacementDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatReplacementDescriptionWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatReplacementDescription response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatReplacementDescription read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatReplacementDescription : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatReplacementDescription()
        : SubscribeAttribute("bat-replacement-description")
    {
    }

    ~SubscribeAttributePowerSourceBatReplacementDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatReplacementDescriptionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatReplacementDescription response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatCommonDesignation
 */
class ReadPowerSourceBatCommonDesignation : public ReadAttribute {
public:
    ReadPowerSourceBatCommonDesignation()
        : ReadAttribute("bat-common-designation")
    {
    }

    ~ReadPowerSourceBatCommonDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatCommonDesignationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatCommonDesignation response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatCommonDesignation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatCommonDesignation : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatCommonDesignation()
        : SubscribeAttribute("bat-common-designation")
    {
    }

    ~SubscribeAttributePowerSourceBatCommonDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatCommonDesignationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatCommonDesignation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatANSIDesignation
 */
class ReadPowerSourceBatANSIDesignation : public ReadAttribute {
public:
    ReadPowerSourceBatANSIDesignation()
        : ReadAttribute("bat-ansidesignation")
    {
    }

    ~ReadPowerSourceBatANSIDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatANSIDesignationWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatANSIDesignation response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatANSIDesignation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatANSIDesignation : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatANSIDesignation()
        : SubscribeAttribute("bat-ansidesignation")
    {
    }

    ~SubscribeAttributePowerSourceBatANSIDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatANSIDesignationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatANSIDesignation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatIECDesignation
 */
class ReadPowerSourceBatIECDesignation : public ReadAttribute {
public:
    ReadPowerSourceBatIECDesignation()
        : ReadAttribute("bat-iecdesignation")
    {
    }

    ~ReadPowerSourceBatIECDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatIECDesignationWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatIECDesignation response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatIECDesignation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatIECDesignation : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatIECDesignation()
        : SubscribeAttribute("bat-iecdesignation")
    {
    }

    ~SubscribeAttributePowerSourceBatIECDesignation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatIECDesignationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatIECDesignation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatApprovedChemistry
 */
class ReadPowerSourceBatApprovedChemistry : public ReadAttribute {
public:
    ReadPowerSourceBatApprovedChemistry()
        : ReadAttribute("bat-approved-chemistry")
    {
    }

    ~ReadPowerSourceBatApprovedChemistry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatApprovedChemistryWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatApprovedChemistry response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatApprovedChemistry read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatApprovedChemistry : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatApprovedChemistry()
        : SubscribeAttribute("bat-approved-chemistry")
    {
    }

    ~SubscribeAttributePowerSourceBatApprovedChemistry() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatApprovedChemistryWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatApprovedChemistry response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatCapacity
 */
class ReadPowerSourceBatCapacity : public ReadAttribute {
public:
    ReadPowerSourceBatCapacity()
        : ReadAttribute("bat-capacity")
    {
    }

    ~ReadPowerSourceBatCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatCapacityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatCapacity response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatCapacity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatCapacity : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatCapacity()
        : SubscribeAttribute("bat-capacity")
    {
    }

    ~SubscribeAttributePowerSourceBatCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatCapacityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatCapacity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatQuantity
 */
class ReadPowerSourceBatQuantity : public ReadAttribute {
public:
    ReadPowerSourceBatQuantity()
        : ReadAttribute("bat-quantity")
    {
    }

    ~ReadPowerSourceBatQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatQuantityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatQuantity response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatQuantity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatQuantity : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatQuantity()
        : SubscribeAttribute("bat-quantity")
    {
    }

    ~SubscribeAttributePowerSourceBatQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatQuantityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatQuantity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatChargeState
 */
class ReadPowerSourceBatChargeState : public ReadAttribute {
public:
    ReadPowerSourceBatChargeState()
        : ReadAttribute("bat-charge-state")
    {
    }

    ~ReadPowerSourceBatChargeState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatChargeStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatChargeState response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatChargeState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatChargeState : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatChargeState()
        : SubscribeAttribute("bat-charge-state")
    {
    }

    ~SubscribeAttributePowerSourceBatChargeState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatChargeStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatChargeState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatTimeToFullCharge
 */
class ReadPowerSourceBatTimeToFullCharge : public ReadAttribute {
public:
    ReadPowerSourceBatTimeToFullCharge()
        : ReadAttribute("bat-time-to-full-charge")
    {
    }

    ~ReadPowerSourceBatTimeToFullCharge() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatTimeToFullChargeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatTimeToFullCharge response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatTimeToFullCharge read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatTimeToFullCharge : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatTimeToFullCharge()
        : SubscribeAttribute("bat-time-to-full-charge")
    {
    }

    ~SubscribeAttributePowerSourceBatTimeToFullCharge() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatTimeToFullChargeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatTimeToFullCharge response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatFunctionalWhileCharging
 */
class ReadPowerSourceBatFunctionalWhileCharging : public ReadAttribute {
public:
    ReadPowerSourceBatFunctionalWhileCharging()
        : ReadAttribute("bat-functional-while-charging")
    {
    }

    ~ReadPowerSourceBatFunctionalWhileCharging() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatFunctionalWhileChargingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatFunctionalWhileCharging response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatFunctionalWhileCharging read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatFunctionalWhileCharging : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatFunctionalWhileCharging()
        : SubscribeAttribute("bat-functional-while-charging")
    {
    }

    ~SubscribeAttributePowerSourceBatFunctionalWhileCharging() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatFunctionalWhileChargingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatFunctionalWhileCharging response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BatChargingCurrent
 */
class ReadPowerSourceBatChargingCurrent : public ReadAttribute {
public:
    ReadPowerSourceBatChargingCurrent()
        : ReadAttribute("bat-charging-current")
    {
    }

    ~ReadPowerSourceBatChargingCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBatChargingCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.BatChargingCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource BatChargingCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceBatChargingCurrent : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceBatChargingCurrent()
        : SubscribeAttribute("bat-charging-current")
    {
    }

    ~SubscribeAttributePowerSourceBatChargingCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBatChargingCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.BatChargingCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveBatChargeFaults
 */
class ReadPowerSourceActiveBatChargeFaults : public ReadAttribute {
public:
    ReadPowerSourceActiveBatChargeFaults()
        : ReadAttribute("active-bat-charge-faults")
    {
    }

    ~ReadPowerSourceActiveBatChargeFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeActiveBatChargeFaultsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ActiveBatChargeFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ActiveBatChargeFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceActiveBatChargeFaults : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceActiveBatChargeFaults()
        : SubscribeAttribute("active-bat-charge-faults")
    {
    }

    ~SubscribeAttributePowerSourceActiveBatChargeFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveBatChargeFaultsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ActiveBatChargeFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPowerSourceGeneratedCommandList : public ReadAttribute {
public:
    ReadPowerSourceGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPowerSourceGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePowerSourceGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPowerSourceAcceptedCommandList : public ReadAttribute {
public:
    ReadPowerSourceAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPowerSourceAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePowerSourceAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPowerSourceAttributeList : public ReadAttribute {
public:
    ReadPowerSourceAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPowerSourceAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePowerSourceAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPowerSourceFeatureMap : public ReadAttribute {
public:
    ReadPowerSourceFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPowerSourceFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePowerSourceFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPowerSourceClusterRevision : public ReadAttribute {
public:
    ReadPowerSourceClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPowerSourceClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PowerSource.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PowerSource ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePowerSourceClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePowerSourceClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePowerSourceClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000002F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPowerSource * cluster = [[MTRBaseClusterPowerSource alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PowerSource.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster GeneralCommissioning                                        | 0x0030 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ArmFailSafe                                                       |   0x00 |
| * SetRegulatoryConfig                                               |   0x02 |
| * CommissioningComplete                                             |   0x04 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Breadcrumb                                                        | 0x0000 |
| * BasicCommissioningInfo                                            | 0x0001 |
| * RegulatoryConfig                                                  | 0x0002 |
| * LocationCapability                                                | 0x0003 |
| * SupportsConcurrentConnection                                      | 0x0004 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ArmFailSafe
 */
class GeneralCommissioningArmFailSafe : public ClusterCommand {
public:
    GeneralCommissioningArmFailSafe()
        : ClusterCommand("arm-fail-safe")
    {
        AddArgument("ExpiryLengthSeconds", 0, UINT16_MAX, &mRequest.expiryLengthSeconds);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRGeneralCommissioningClusterArmFailSafeParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.expiryLengthSeconds = [NSNumber numberWithUnsignedShort:mRequest.expiryLengthSeconds];
        params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster armFailSafeWithParams:params
                                completion:^(MTRGeneralCommissioningClusterArmFailSafeResponseParams * _Nullable values,
                                    NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafe::Type mRequest;
};

/*
 * Command SetRegulatoryConfig
 */
class GeneralCommissioningSetRegulatoryConfig : public ClusterCommand {
public:
    GeneralCommissioningSetRegulatoryConfig()
        : ClusterCommand("set-regulatory-config")
    {
        AddArgument("NewRegulatoryConfig", 0, UINT8_MAX, &mRequest.newRegulatoryConfig);
        AddArgument("CountryCode", &mRequest.countryCode);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRGeneralCommissioningClusterSetRegulatoryConfigParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.newRegulatoryConfig = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.newRegulatoryConfig)];
        params.countryCode = [[NSString alloc] initWithBytes:mRequest.countryCode.data()
                                                      length:mRequest.countryCode.size()
                                                    encoding:NSUTF8StringEncoding];
        params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                setRegulatoryConfigWithParams:params
                                   completion:^(MTRGeneralCommissioningClusterSetRegulatoryConfigResponseParams * _Nullable values,
                                       NSError * _Nullable error) {
                                       NSLog(@"Values: %@", values);
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GeneralCommissioning::Commands::SetRegulatoryConfig::Type mRequest;
};

/*
 * Command CommissioningComplete
 */
class GeneralCommissioningCommissioningComplete : public ClusterCommand {
public:
    GeneralCommissioningCommissioningComplete()
        : ClusterCommand("commissioning-complete")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRGeneralCommissioningClusterCommissioningCompleteParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster commissioningCompleteWithParams:params
                                          completion:^(
                                              MTRGeneralCommissioningClusterCommissioningCompleteResponseParams * _Nullable values,
                                              NSError * _Nullable error) {
                                              NSLog(@"Values: %@", values);
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute Breadcrumb
 */
class ReadGeneralCommissioningBreadcrumb : public ReadAttribute {
public:
    ReadGeneralCommissioningBreadcrumb()
        : ReadAttribute("breadcrumb")
    {
    }

    ~ReadGeneralCommissioningBreadcrumb() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBreadcrumbWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.Breadcrumb response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning Breadcrumb read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteGeneralCommissioningBreadcrumb : public WriteAttribute {
public:
    WriteGeneralCommissioningBreadcrumb()
        : WriteAttribute("breadcrumb")
    {
        AddArgument("attr-name", "breadcrumb");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteGeneralCommissioningBreadcrumb() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeBreadcrumbWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("GeneralCommissioning Breadcrumb write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeGeneralCommissioningBreadcrumb : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningBreadcrumb()
        : SubscribeAttribute("breadcrumb")
    {
    }

    ~SubscribeAttributeGeneralCommissioningBreadcrumb() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBreadcrumbWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.Breadcrumb response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BasicCommissioningInfo
 */
class ReadGeneralCommissioningBasicCommissioningInfo : public ReadAttribute {
public:
    ReadGeneralCommissioningBasicCommissioningInfo()
        : ReadAttribute("basic-commissioning-info")
    {
    }

    ~ReadGeneralCommissioningBasicCommissioningInfo() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBasicCommissioningInfoWithCompletion:^(
            MTRGeneralCommissioningClusterBasicCommissioningInfo * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.BasicCommissioningInfo response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning BasicCommissioningInfo read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningBasicCommissioningInfo : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningBasicCommissioningInfo()
        : SubscribeAttribute("basic-commissioning-info")
    {
    }

    ~SubscribeAttributeGeneralCommissioningBasicCommissioningInfo() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBasicCommissioningInfoWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRGeneralCommissioningClusterBasicCommissioningInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.BasicCommissioningInfo response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RegulatoryConfig
 */
class ReadGeneralCommissioningRegulatoryConfig : public ReadAttribute {
public:
    ReadGeneralCommissioningRegulatoryConfig()
        : ReadAttribute("regulatory-config")
    {
    }

    ~ReadGeneralCommissioningRegulatoryConfig() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeRegulatoryConfigWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.RegulatoryConfig response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning RegulatoryConfig read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningRegulatoryConfig : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningRegulatoryConfig()
        : SubscribeAttribute("regulatory-config")
    {
    }

    ~SubscribeAttributeGeneralCommissioningRegulatoryConfig() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRegulatoryConfigWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.RegulatoryConfig response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocationCapability
 */
class ReadGeneralCommissioningLocationCapability : public ReadAttribute {
public:
    ReadGeneralCommissioningLocationCapability()
        : ReadAttribute("location-capability")
    {
    }

    ~ReadGeneralCommissioningLocationCapability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLocationCapabilityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.LocationCapability response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning LocationCapability read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningLocationCapability : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningLocationCapability()
        : SubscribeAttribute("location-capability")
    {
    }

    ~SubscribeAttributeGeneralCommissioningLocationCapability() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLocationCapabilityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.LocationCapability response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportsConcurrentConnection
 */
class ReadGeneralCommissioningSupportsConcurrentConnection : public ReadAttribute {
public:
    ReadGeneralCommissioningSupportsConcurrentConnection()
        : ReadAttribute("supports-concurrent-connection")
    {
    }

    ~ReadGeneralCommissioningSupportsConcurrentConnection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeSupportsConcurrentConnectionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.SupportsConcurrentConnection response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning SupportsConcurrentConnection read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection()
        : SubscribeAttribute("supports-concurrent-connection")
    {
    }

    ~SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportsConcurrentConnectionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.SupportsConcurrentConnection response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGeneralCommissioningGeneratedCommandList : public ReadAttribute {
public:
    ReadGeneralCommissioningGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGeneralCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGeneralCommissioningAcceptedCommandList : public ReadAttribute {
public:
    ReadGeneralCommissioningAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGeneralCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGeneralCommissioningAttributeList : public ReadAttribute {
public:
    ReadGeneralCommissioningAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGeneralCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGeneralCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGeneralCommissioningFeatureMap : public ReadAttribute {
public:
    ReadGeneralCommissioningFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGeneralCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGeneralCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGeneralCommissioningClusterRevision : public ReadAttribute {
public:
    ReadGeneralCommissioningClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGeneralCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralCommissioning.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralCommissioning ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralCommissioningClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralCommissioningClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGeneralCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000030) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralCommissioning * cluster = [[MTRBaseClusterGeneralCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralCommissioning.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster NetworkCommissioning                                        | 0x0031 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ScanNetworks                                                      |   0x00 |
| * AddOrUpdateWiFiNetwork                                            |   0x02 |
| * AddOrUpdateThreadNetwork                                          |   0x03 |
| * RemoveNetwork                                                     |   0x04 |
| * ConnectNetwork                                                    |   0x06 |
| * ReorderNetwork                                                    |   0x08 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MaxNetworks                                                       | 0x0000 |
| * Networks                                                          | 0x0001 |
| * ScanMaxTimeSeconds                                                | 0x0002 |
| * ConnectMaxTimeSeconds                                             | 0x0003 |
| * InterfaceEnabled                                                  | 0x0004 |
| * LastNetworkingStatus                                              | 0x0005 |
| * LastNetworkID                                                     | 0x0006 |
| * LastConnectErrorValue                                             | 0x0007 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ScanNetworks
 */
class NetworkCommissioningScanNetworks : public ClusterCommand {
public:
    NetworkCommissioningScanNetworks()
        : ClusterCommand("scan-networks")
    {
        AddArgument("Ssid", &mRequest.ssid);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRNetworkCommissioningClusterScanNetworksParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.ssid.HasValue()) {
            if (mRequest.ssid.Value().IsNull()) {
                params.ssid = nil;
            } else {
                params.ssid = [NSData dataWithBytes:mRequest.ssid.Value().Value().data()
                                             length:mRequest.ssid.Value().Value().size()];
            }
        } else {
            params.ssid = nil;
        }
        if (mRequest.breadcrumb.HasValue()) {
            params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb.Value()];
        } else {
            params.breadcrumb = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster scanNetworksWithParams:params
                                 completion:^(MTRNetworkCommissioningClusterScanNetworksResponseParams * _Nullable values,
                                     NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::ScanNetworks::Type mRequest;
};

/*
 * Command AddOrUpdateWiFiNetwork
 */
class NetworkCommissioningAddOrUpdateWiFiNetwork : public ClusterCommand {
public:
    NetworkCommissioningAddOrUpdateWiFiNetwork()
        : ClusterCommand("add-or-update-wi-fi-network")
    {
        AddArgument("Ssid", &mRequest.ssid);
        AddArgument("Credentials", &mRequest.credentials);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRNetworkCommissioningClusterAddOrUpdateWiFiNetworkParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.ssid = [NSData dataWithBytes:mRequest.ssid.data() length:mRequest.ssid.size()];
        params.credentials = [NSData dataWithBytes:mRequest.credentials.data() length:mRequest.credentials.size()];
        if (mRequest.breadcrumb.HasValue()) {
            params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb.Value()];
        } else {
            params.breadcrumb = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                addOrUpdateWiFiNetworkWithParams:params
                                      completion:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                          NSError * _Nullable error) {
                                          NSLog(@"Values: %@", values);
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::AddOrUpdateWiFiNetwork::Type mRequest;
};

/*
 * Command AddOrUpdateThreadNetwork
 */
class NetworkCommissioningAddOrUpdateThreadNetwork : public ClusterCommand {
public:
    NetworkCommissioningAddOrUpdateThreadNetwork()
        : ClusterCommand("add-or-update-thread-network")
    {
        AddArgument("OperationalDataset", &mRequest.operationalDataset);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRNetworkCommissioningClusterAddOrUpdateThreadNetworkParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.operationalDataset = [NSData dataWithBytes:mRequest.operationalDataset.data()
                                                   length:mRequest.operationalDataset.size()];
        if (mRequest.breadcrumb.HasValue()) {
            params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb.Value()];
        } else {
            params.breadcrumb = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                addOrUpdateThreadNetworkWithParams:params
                                        completion:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                            NSError * _Nullable error) {
                                            NSLog(@"Values: %@", values);
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::AddOrUpdateThreadNetwork::Type mRequest;
};

/*
 * Command RemoveNetwork
 */
class NetworkCommissioningRemoveNetwork : public ClusterCommand {
public:
    NetworkCommissioningRemoveNetwork()
        : ClusterCommand("remove-network")
    {
        AddArgument("NetworkID", &mRequest.networkID);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRNetworkCommissioningClusterRemoveNetworkParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.networkID = [NSData dataWithBytes:mRequest.networkID.data() length:mRequest.networkID.size()];
        if (mRequest.breadcrumb.HasValue()) {
            params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb.Value()];
        } else {
            params.breadcrumb = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster removeNetworkWithParams:params
                                  completion:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                      NSError * _Nullable error) {
                                      NSLog(@"Values: %@", values);
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::RemoveNetwork::Type mRequest;
};

/*
 * Command ConnectNetwork
 */
class NetworkCommissioningConnectNetwork : public ClusterCommand {
public:
    NetworkCommissioningConnectNetwork()
        : ClusterCommand("connect-network")
    {
        AddArgument("NetworkID", &mRequest.networkID);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRNetworkCommissioningClusterConnectNetworkParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.networkID = [NSData dataWithBytes:mRequest.networkID.data() length:mRequest.networkID.size()];
        if (mRequest.breadcrumb.HasValue()) {
            params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb.Value()];
        } else {
            params.breadcrumb = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster connectNetworkWithParams:params
                                   completion:^(MTRNetworkCommissioningClusterConnectNetworkResponseParams * _Nullable values,
                                       NSError * _Nullable error) {
                                       NSLog(@"Values: %@", values);
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::ConnectNetwork::Type mRequest;
};

/*
 * Command ReorderNetwork
 */
class NetworkCommissioningReorderNetwork : public ClusterCommand {
public:
    NetworkCommissioningReorderNetwork()
        : ClusterCommand("reorder-network")
    {
        AddArgument("NetworkID", &mRequest.networkID);
        AddArgument("NetworkIndex", 0, UINT8_MAX, &mRequest.networkIndex);
        AddArgument("Breadcrumb", 0, UINT64_MAX, &mRequest.breadcrumb);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRNetworkCommissioningClusterReorderNetworkParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.networkID = [NSData dataWithBytes:mRequest.networkID.data() length:mRequest.networkID.size()];
        params.networkIndex = [NSNumber numberWithUnsignedChar:mRequest.networkIndex];
        if (mRequest.breadcrumb.HasValue()) {
            params.breadcrumb = [NSNumber numberWithUnsignedLongLong:mRequest.breadcrumb.Value()];
        } else {
            params.breadcrumb = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster reorderNetworkWithParams:params
                                   completion:^(MTRNetworkCommissioningClusterNetworkConfigResponseParams * _Nullable values,
                                       NSError * _Nullable error) {
                                       NSLog(@"Values: %@", values);
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::NetworkCommissioning::Commands::ReorderNetwork::Type mRequest;
};

/*
 * Attribute MaxNetworks
 */
class ReadNetworkCommissioningMaxNetworks : public ReadAttribute {
public:
    ReadNetworkCommissioningMaxNetworks()
        : ReadAttribute("max-networks")
    {
    }

    ~ReadNetworkCommissioningMaxNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeMaxNetworksWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.MaxNetworks response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning MaxNetworks read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningMaxNetworks : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningMaxNetworks()
        : SubscribeAttribute("max-networks")
    {
    }

    ~SubscribeAttributeNetworkCommissioningMaxNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxNetworksWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.MaxNetworks response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Networks
 */
class ReadNetworkCommissioningNetworks : public ReadAttribute {
public:
    ReadNetworkCommissioningNetworks()
        : ReadAttribute("networks")
    {
    }

    ~ReadNetworkCommissioningNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeNetworksWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.Networks response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning Networks read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningNetworks : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningNetworks()
        : SubscribeAttribute("networks")
    {
    }

    ~SubscribeAttributeNetworkCommissioningNetworks() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNetworksWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.Networks response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScanMaxTimeSeconds
 */
class ReadNetworkCommissioningScanMaxTimeSeconds : public ReadAttribute {
public:
    ReadNetworkCommissioningScanMaxTimeSeconds()
        : ReadAttribute("scan-max-time-seconds")
    {
    }

    ~ReadNetworkCommissioningScanMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeScanMaxTimeSecondsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.ScanMaxTimeSeconds response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning ScanMaxTimeSeconds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds()
        : SubscribeAttribute("scan-max-time-seconds")
    {
    }

    ~SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeScanMaxTimeSecondsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.ScanMaxTimeSeconds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ConnectMaxTimeSeconds
 */
class ReadNetworkCommissioningConnectMaxTimeSeconds : public ReadAttribute {
public:
    ReadNetworkCommissioningConnectMaxTimeSeconds()
        : ReadAttribute("connect-max-time-seconds")
    {
    }

    ~ReadNetworkCommissioningConnectMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeConnectMaxTimeSecondsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.ConnectMaxTimeSeconds response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning ConnectMaxTimeSeconds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds()
        : SubscribeAttribute("connect-max-time-seconds")
    {
    }

    ~SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeConnectMaxTimeSecondsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.ConnectMaxTimeSeconds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InterfaceEnabled
 */
class ReadNetworkCommissioningInterfaceEnabled : public ReadAttribute {
public:
    ReadNetworkCommissioningInterfaceEnabled()
        : ReadAttribute("interface-enabled")
    {
    }

    ~ReadNetworkCommissioningInterfaceEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeInterfaceEnabledWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.InterfaceEnabled response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning InterfaceEnabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteNetworkCommissioningInterfaceEnabled : public WriteAttribute {
public:
    WriteNetworkCommissioningInterfaceEnabled()
        : WriteAttribute("interface-enabled")
    {
        AddArgument("attr-name", "interface-enabled");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteNetworkCommissioningInterfaceEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeInterfaceEnabledWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("NetworkCommissioning InterfaceEnabled write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeNetworkCommissioningInterfaceEnabled : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningInterfaceEnabled()
        : SubscribeAttribute("interface-enabled")
    {
    }

    ~SubscribeAttributeNetworkCommissioningInterfaceEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInterfaceEnabledWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.InterfaceEnabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastNetworkingStatus
 */
class ReadNetworkCommissioningLastNetworkingStatus : public ReadAttribute {
public:
    ReadNetworkCommissioningLastNetworkingStatus()
        : ReadAttribute("last-networking-status")
    {
    }

    ~ReadNetworkCommissioningLastNetworkingStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLastNetworkingStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.LastNetworkingStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning LastNetworkingStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningLastNetworkingStatus : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningLastNetworkingStatus()
        : SubscribeAttribute("last-networking-status")
    {
    }

    ~SubscribeAttributeNetworkCommissioningLastNetworkingStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLastNetworkingStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.LastNetworkingStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastNetworkID
 */
class ReadNetworkCommissioningLastNetworkID : public ReadAttribute {
public:
    ReadNetworkCommissioningLastNetworkID()
        : ReadAttribute("last-network-id")
    {
    }

    ~ReadNetworkCommissioningLastNetworkID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLastNetworkIDWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.LastNetworkID response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning LastNetworkID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningLastNetworkID : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningLastNetworkID()
        : SubscribeAttribute("last-network-id")
    {
    }

    ~SubscribeAttributeNetworkCommissioningLastNetworkID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLastNetworkIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.LastNetworkID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LastConnectErrorValue
 */
class ReadNetworkCommissioningLastConnectErrorValue : public ReadAttribute {
public:
    ReadNetworkCommissioningLastConnectErrorValue()
        : ReadAttribute("last-connect-error-value")
    {
    }

    ~ReadNetworkCommissioningLastConnectErrorValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLastConnectErrorValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.LastConnectErrorValue response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning LastConnectErrorValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningLastConnectErrorValue : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningLastConnectErrorValue()
        : SubscribeAttribute("last-connect-error-value")
    {
    }

    ~SubscribeAttributeNetworkCommissioningLastConnectErrorValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLastConnectErrorValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.LastConnectErrorValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadNetworkCommissioningGeneratedCommandList : public ReadAttribute {
public:
    ReadNetworkCommissioningGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadNetworkCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadNetworkCommissioningAcceptedCommandList : public ReadAttribute {
public:
    ReadNetworkCommissioningAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadNetworkCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadNetworkCommissioningAttributeList : public ReadAttribute {
public:
    ReadNetworkCommissioningAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadNetworkCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeNetworkCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadNetworkCommissioningFeatureMap : public ReadAttribute {
public:
    ReadNetworkCommissioningFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadNetworkCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeNetworkCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadNetworkCommissioningClusterRevision : public ReadAttribute {
public:
    ReadNetworkCommissioningClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadNetworkCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"NetworkCommissioning.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("NetworkCommissioning ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeNetworkCommissioningClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeNetworkCommissioningClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeNetworkCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000031) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterNetworkCommissioning * cluster = [[MTRBaseClusterNetworkCommissioning alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"NetworkCommissioning.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster DiagnosticLogs                                              | 0x0032 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * RetrieveLogsRequest                                               |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command RetrieveLogsRequest
 */
class DiagnosticLogsRetrieveLogsRequest : public ClusterCommand {
public:
    DiagnosticLogsRetrieveLogsRequest()
        : ClusterCommand("retrieve-logs-request")
    {
        AddArgument("Intent", 0, UINT8_MAX, &mRequest.intent);
        AddArgument("RequestedProtocol", 0, UINT8_MAX, &mRequest.requestedProtocol);
        AddArgument("TransferFileDesignator", &mRequest.transferFileDesignator);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRDiagnosticLogsClusterRetrieveLogsRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.intent = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.intent)];
        params.requestedProtocol = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.requestedProtocol)];
        params.transferFileDesignator = [NSData dataWithBytes:mRequest.transferFileDesignator.data()
                                                       length:mRequest.transferFileDesignator.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster retrieveLogsRequestWithParams:params
                                        completion:^(MTRDiagnosticLogsClusterRetrieveLogsResponseParams * _Nullable values,
                                            NSError * _Nullable error) {
                                            NSLog(@"Values: %@", values);
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DiagnosticLogs::Commands::RetrieveLogsRequest::Type mRequest;
};

/*
 * Attribute GeneratedCommandList
 */
class ReadDiagnosticLogsGeneratedCommandList : public ReadAttribute {
public:
    ReadDiagnosticLogsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadDiagnosticLogsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadDiagnosticLogsAcceptedCommandList : public ReadAttribute {
public:
    ReadDiagnosticLogsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadDiagnosticLogsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadDiagnosticLogsAttributeList : public ReadAttribute {
public:
    ReadDiagnosticLogsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadDiagnosticLogsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeDiagnosticLogsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadDiagnosticLogsFeatureMap : public ReadAttribute {
public:
    ReadDiagnosticLogsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadDiagnosticLogsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeDiagnosticLogsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadDiagnosticLogsClusterRevision : public ReadAttribute {
public:
    ReadDiagnosticLogsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadDiagnosticLogsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DiagnosticLogs.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("DiagnosticLogs ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDiagnosticLogsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeDiagnosticLogsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeDiagnosticLogsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000032) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDiagnosticLogs * cluster = [[MTRBaseClusterDiagnosticLogs alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DiagnosticLogs.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster GeneralDiagnostics                                          | 0x0033 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * TestEventTrigger                                                  |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NetworkInterfaces                                                 | 0x0000 |
| * RebootCount                                                       | 0x0001 |
| * UpTime                                                            | 0x0002 |
| * TotalOperationalHours                                             | 0x0003 |
| * BootReasons                                                       | 0x0004 |
| * ActiveHardwareFaults                                              | 0x0005 |
| * ActiveRadioFaults                                                 | 0x0006 |
| * ActiveNetworkFaults                                               | 0x0007 |
| * TestEventTriggersEnabled                                          | 0x0008 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * HardwareFaultChange                                               | 0x0000 |
| * RadioFaultChange                                                  | 0x0001 |
| * NetworkFaultChange                                                | 0x0002 |
| * BootReason                                                        | 0x0003 |
\*----------------------------------------------------------------------------*/

/*
 * Command TestEventTrigger
 */
class GeneralDiagnosticsTestEventTrigger : public ClusterCommand {
public:
    GeneralDiagnosticsTestEventTrigger()
        : ClusterCommand("test-event-trigger")
    {
        AddArgument("EnableKey", &mRequest.enableKey);
        AddArgument("EventTrigger", 0, UINT64_MAX, &mRequest.eventTrigger);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRGeneralDiagnosticsClusterTestEventTriggerParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.enableKey = [NSData dataWithBytes:mRequest.enableKey.data() length:mRequest.enableKey.size()];
        params.eventTrigger = [NSNumber numberWithUnsignedLongLong:mRequest.eventTrigger];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testEventTriggerWithParams:params
                                     completion:^(NSError * _Nullable error) {
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GeneralDiagnostics::Commands::TestEventTrigger::Type mRequest;
};

/*
 * Attribute NetworkInterfaces
 */
class ReadGeneralDiagnosticsNetworkInterfaces : public ReadAttribute {
public:
    ReadGeneralDiagnosticsNetworkInterfaces()
        : ReadAttribute("network-interfaces")
    {
    }

    ~ReadGeneralDiagnosticsNetworkInterfaces() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeNetworkInterfacesWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.NetworkInterfaces response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics NetworkInterfaces read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsNetworkInterfaces : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsNetworkInterfaces()
        : SubscribeAttribute("network-interfaces")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsNetworkInterfaces() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNetworkInterfacesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.NetworkInterfaces response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RebootCount
 */
class ReadGeneralDiagnosticsRebootCount : public ReadAttribute {
public:
    ReadGeneralDiagnosticsRebootCount()
        : ReadAttribute("reboot-count")
    {
    }

    ~ReadGeneralDiagnosticsRebootCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeRebootCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.RebootCount response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics RebootCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsRebootCount : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsRebootCount()
        : SubscribeAttribute("reboot-count")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsRebootCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRebootCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.RebootCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UpTime
 */
class ReadGeneralDiagnosticsUpTime : public ReadAttribute {
public:
    ReadGeneralDiagnosticsUpTime()
        : ReadAttribute("up-time")
    {
    }

    ~ReadGeneralDiagnosticsUpTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeUpTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.UpTime response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics UpTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsUpTime : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsUpTime()
        : SubscribeAttribute("up-time")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsUpTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUpTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.UpTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalOperationalHours
 */
class ReadGeneralDiagnosticsTotalOperationalHours : public ReadAttribute {
public:
    ReadGeneralDiagnosticsTotalOperationalHours()
        : ReadAttribute("total-operational-hours")
    {
    }

    ~ReadGeneralDiagnosticsTotalOperationalHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeTotalOperationalHoursWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.TotalOperationalHours response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics TotalOperationalHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsTotalOperationalHours : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsTotalOperationalHours()
        : SubscribeAttribute("total-operational-hours")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsTotalOperationalHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTotalOperationalHoursWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.TotalOperationalHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BootReasons
 */
class ReadGeneralDiagnosticsBootReasons : public ReadAttribute {
public:
    ReadGeneralDiagnosticsBootReasons()
        : ReadAttribute("boot-reasons")
    {
    }

    ~ReadGeneralDiagnosticsBootReasons() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeBootReasonsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.BootReasons response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics BootReasons read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsBootReasons : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsBootReasons()
        : SubscribeAttribute("boot-reasons")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsBootReasons() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBootReasonsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.BootReasons response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveHardwareFaults
 */
class ReadGeneralDiagnosticsActiveHardwareFaults : public ReadAttribute {
public:
    ReadGeneralDiagnosticsActiveHardwareFaults()
        : ReadAttribute("active-hardware-faults")
    {
    }

    ~ReadGeneralDiagnosticsActiveHardwareFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeActiveHardwareFaultsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ActiveHardwareFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ActiveHardwareFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults()
        : SubscribeAttribute("active-hardware-faults")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveHardwareFaultsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ActiveHardwareFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveRadioFaults
 */
class ReadGeneralDiagnosticsActiveRadioFaults : public ReadAttribute {
public:
    ReadGeneralDiagnosticsActiveRadioFaults()
        : ReadAttribute("active-radio-faults")
    {
    }

    ~ReadGeneralDiagnosticsActiveRadioFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeActiveRadioFaultsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ActiveRadioFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ActiveRadioFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsActiveRadioFaults : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsActiveRadioFaults()
        : SubscribeAttribute("active-radio-faults")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsActiveRadioFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveRadioFaultsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ActiveRadioFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveNetworkFaults
 */
class ReadGeneralDiagnosticsActiveNetworkFaults : public ReadAttribute {
public:
    ReadGeneralDiagnosticsActiveNetworkFaults()
        : ReadAttribute("active-network-faults")
    {
    }

    ~ReadGeneralDiagnosticsActiveNetworkFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeActiveNetworkFaultsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ActiveNetworkFaults response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ActiveNetworkFaults read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults()
        : SubscribeAttribute("active-network-faults")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveNetworkFaultsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ActiveNetworkFaults response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TestEventTriggersEnabled
 */
class ReadGeneralDiagnosticsTestEventTriggersEnabled : public ReadAttribute {
public:
    ReadGeneralDiagnosticsTestEventTriggersEnabled()
        : ReadAttribute("test-event-triggers-enabled")
    {
    }

    ~ReadGeneralDiagnosticsTestEventTriggersEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeTestEventTriggersEnabledWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.TestEventTriggersEnabled response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics TestEventTriggersEnabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled()
        : SubscribeAttribute("test-event-triggers-enabled")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTestEventTriggersEnabledWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.TestEventTriggersEnabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGeneralDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGeneralDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGeneralDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGeneralDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGeneralDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadGeneralDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGeneralDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGeneralDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadGeneralDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGeneralDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGeneralDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadGeneralDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGeneralDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GeneralDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("GeneralDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGeneralDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGeneralDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGeneralDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000033) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGeneralDiagnostics * cluster = [[MTRBaseClusterGeneralDiagnostics alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GeneralDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster SoftwareDiagnostics                                         | 0x0034 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetWatermarks                                                   |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ThreadMetrics                                                     | 0x0000 |
| * CurrentHeapFree                                                   | 0x0001 |
| * CurrentHeapUsed                                                   | 0x0002 |
| * CurrentHeapHighWatermark                                          | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SoftwareFault                                                     | 0x0000 |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetWatermarks
 */
class SoftwareDiagnosticsResetWatermarks : public ClusterCommand {
public:
    SoftwareDiagnosticsResetWatermarks()
        : ClusterCommand("reset-watermarks")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRSoftwareDiagnosticsClusterResetWatermarksParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster resetWatermarksWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute ThreadMetrics
 */
class ReadSoftwareDiagnosticsThreadMetrics : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsThreadMetrics()
        : ReadAttribute("thread-metrics")
    {
    }

    ~ReadSoftwareDiagnosticsThreadMetrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeThreadMetricsWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.ThreadMetrics response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics ThreadMetrics read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsThreadMetrics : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsThreadMetrics()
        : SubscribeAttribute("thread-metrics")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsThreadMetrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeThreadMetricsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.ThreadMetrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentHeapFree
 */
class ReadSoftwareDiagnosticsCurrentHeapFree : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsCurrentHeapFree()
        : ReadAttribute("current-heap-free")
    {
    }

    ~ReadSoftwareDiagnosticsCurrentHeapFree() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentHeapFreeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.CurrentHeapFree response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics CurrentHeapFree read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree()
        : SubscribeAttribute("current-heap-free")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentHeapFreeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapFree response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentHeapUsed
 */
class ReadSoftwareDiagnosticsCurrentHeapUsed : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsCurrentHeapUsed()
        : ReadAttribute("current-heap-used")
    {
    }

    ~ReadSoftwareDiagnosticsCurrentHeapUsed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentHeapUsedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.CurrentHeapUsed response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics CurrentHeapUsed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed()
        : SubscribeAttribute("current-heap-used")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentHeapUsedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapUsed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentHeapHighWatermark
 */
class ReadSoftwareDiagnosticsCurrentHeapHighWatermark : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsCurrentHeapHighWatermark()
        : ReadAttribute("current-heap-high-watermark")
    {
    }

    ~ReadSoftwareDiagnosticsCurrentHeapHighWatermark() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentHeapHighWatermarkWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.CurrentHeapHighWatermark response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics CurrentHeapHighWatermark read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark()
        : SubscribeAttribute("current-heap-high-watermark")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentHeapHighWatermarkWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.CurrentHeapHighWatermark response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadSoftwareDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadSoftwareDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadSoftwareDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadSoftwareDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadSoftwareDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadSoftwareDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadSoftwareDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadSoftwareDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadSoftwareDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadSoftwareDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadSoftwareDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"SoftwareDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("SoftwareDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSoftwareDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeSoftwareDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeSoftwareDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000034) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSoftwareDiagnostics * cluster = [[MTRBaseClusterSoftwareDiagnostics alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"SoftwareDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ThreadNetworkDiagnostics                                    | 0x0035 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCounts                                                       |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Channel                                                           | 0x0000 |
| * RoutingRole                                                       | 0x0001 |
| * NetworkName                                                       | 0x0002 |
| * PanId                                                             | 0x0003 |
| * ExtendedPanId                                                     | 0x0004 |
| * MeshLocalPrefix                                                   | 0x0005 |
| * OverrunCount                                                      | 0x0006 |
| * NeighborTableList                                                 | 0x0007 |
| * RouteTableList                                                    | 0x0008 |
| * PartitionId                                                       | 0x0009 |
| * Weighting                                                         | 0x000A |
| * DataVersion                                                       | 0x000B |
| * StableDataVersion                                                 | 0x000C |
| * LeaderRouterId                                                    | 0x000D |
| * DetachedRoleCount                                                 | 0x000E |
| * ChildRoleCount                                                    | 0x000F |
| * RouterRoleCount                                                   | 0x0010 |
| * LeaderRoleCount                                                   | 0x0011 |
| * AttachAttemptCount                                                | 0x0012 |
| * PartitionIdChangeCount                                            | 0x0013 |
| * BetterPartitionAttachAttemptCount                                 | 0x0014 |
| * ParentChangeCount                                                 | 0x0015 |
| * TxTotalCount                                                      | 0x0016 |
| * TxUnicastCount                                                    | 0x0017 |
| * TxBroadcastCount                                                  | 0x0018 |
| * TxAckRequestedCount                                               | 0x0019 |
| * TxAckedCount                                                      | 0x001A |
| * TxNoAckRequestedCount                                             | 0x001B |
| * TxDataCount                                                       | 0x001C |
| * TxDataPollCount                                                   | 0x001D |
| * TxBeaconCount                                                     | 0x001E |
| * TxBeaconRequestCount                                              | 0x001F |
| * TxOtherCount                                                      | 0x0020 |
| * TxRetryCount                                                      | 0x0021 |
| * TxDirectMaxRetryExpiryCount                                       | 0x0022 |
| * TxIndirectMaxRetryExpiryCount                                     | 0x0023 |
| * TxErrCcaCount                                                     | 0x0024 |
| * TxErrAbortCount                                                   | 0x0025 |
| * TxErrBusyChannelCount                                             | 0x0026 |
| * RxTotalCount                                                      | 0x0027 |
| * RxUnicastCount                                                    | 0x0028 |
| * RxBroadcastCount                                                  | 0x0029 |
| * RxDataCount                                                       | 0x002A |
| * RxDataPollCount                                                   | 0x002B |
| * RxBeaconCount                                                     | 0x002C |
| * RxBeaconRequestCount                                              | 0x002D |
| * RxOtherCount                                                      | 0x002E |
| * RxAddressFilteredCount                                            | 0x002F |
| * RxDestAddrFilteredCount                                           | 0x0030 |
| * RxDuplicatedCount                                                 | 0x0031 |
| * RxErrNoFrameCount                                                 | 0x0032 |
| * RxErrUnknownNeighborCount                                         | 0x0033 |
| * RxErrInvalidSrcAddrCount                                          | 0x0034 |
| * RxErrSecCount                                                     | 0x0035 |
| * RxErrFcsCount                                                     | 0x0036 |
| * RxErrOtherCount                                                   | 0x0037 |
| * ActiveTimestamp                                                   | 0x0038 |
| * PendingTimestamp                                                  | 0x0039 |
| * Delay                                                             | 0x003A |
| * SecurityPolicy                                                    | 0x003B |
| * ChannelPage0Mask                                                  | 0x003C |
| * OperationalDatasetComponents                                      | 0x003D |
| * ActiveNetworkFaultsList                                           | 0x003E |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * ConnectionStatus                                                  | 0x0000 |
| * NetworkFaultChange                                                | 0x0001 |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCounts
 */
class ThreadNetworkDiagnosticsResetCounts : public ClusterCommand {
public:
    ThreadNetworkDiagnosticsResetCounts()
        : ClusterCommand("reset-counts")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRThreadNetworkDiagnosticsClusterResetCountsParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster resetCountsWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute Channel
 */
class ReadThreadNetworkDiagnosticsChannel : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsChannel()
        : ReadAttribute("channel")
    {
    }

    ~ReadThreadNetworkDiagnosticsChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeChannelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.Channel response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics Channel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsChannel : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsChannel()
        : SubscribeAttribute("channel")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeChannelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.Channel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RoutingRole
 */
class ReadThreadNetworkDiagnosticsRoutingRole : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRoutingRole()
        : ReadAttribute("routing-role")
    {
    }

    ~ReadThreadNetworkDiagnosticsRoutingRole() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRoutingRoleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RoutingRole response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RoutingRole read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRoutingRole : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRoutingRole()
        : SubscribeAttribute("routing-role")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRoutingRole() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRoutingRoleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RoutingRole response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NetworkName
 */
class ReadThreadNetworkDiagnosticsNetworkName : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsNetworkName()
        : ReadAttribute("network-name")
    {
    }

    ~ReadThreadNetworkDiagnosticsNetworkName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeNetworkNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.NetworkName response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics NetworkName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsNetworkName : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsNetworkName()
        : SubscribeAttribute("network-name")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsNetworkName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNetworkNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.NetworkName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PanId
 */
class ReadThreadNetworkDiagnosticsPanId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPanId()
        : ReadAttribute("pan-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePanIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PanId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PanId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPanId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPanId()
        : SubscribeAttribute("pan-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePanIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PanId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ExtendedPanId
 */
class ReadThreadNetworkDiagnosticsExtendedPanId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsExtendedPanId()
        : ReadAttribute("extended-pan-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsExtendedPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeExtendedPanIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ExtendedPanId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ExtendedPanId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId()
        : SubscribeAttribute("extended-pan-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeExtendedPanIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ExtendedPanId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeshLocalPrefix
 */
class ReadThreadNetworkDiagnosticsMeshLocalPrefix : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsMeshLocalPrefix()
        : ReadAttribute("mesh-local-prefix")
    {
    }

    ~ReadThreadNetworkDiagnosticsMeshLocalPrefix() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMeshLocalPrefixWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.MeshLocalPrefix response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics MeshLocalPrefix read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix()
        : SubscribeAttribute("mesh-local-prefix")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeshLocalPrefixWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.MeshLocalPrefix response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverrunCount
 */
class ReadThreadNetworkDiagnosticsOverrunCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsOverrunCount()
        : ReadAttribute("overrun-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeOverrunCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.OverrunCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics OverrunCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsOverrunCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsOverrunCount()
        : SubscribeAttribute("overrun-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOverrunCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.OverrunCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NeighborTableList
 */
class ReadThreadNetworkDiagnosticsNeighborTableList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsNeighborTableList()
        : ReadAttribute("neighbor-table-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsNeighborTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeNeighborTableListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.NeighborTableList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics NeighborTableList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList()
        : SubscribeAttribute("neighbor-table-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNeighborTableListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.NeighborTableList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RouteTableList
 */
class ReadThreadNetworkDiagnosticsRouteTableList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRouteTableList()
        : ReadAttribute("route-table-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsRouteTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRouteTableListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RouteTableList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RouteTableList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRouteTableList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRouteTableList()
        : SubscribeAttribute("route-table-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRouteTableList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRouteTableListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RouteTableList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartitionId
 */
class ReadThreadNetworkDiagnosticsPartitionId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPartitionId()
        : ReadAttribute("partition-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsPartitionId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePartitionIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PartitionId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PartitionId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPartitionId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPartitionId()
        : SubscribeAttribute("partition-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPartitionId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePartitionIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PartitionId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Weighting
 */
class ReadThreadNetworkDiagnosticsWeighting : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsWeighting()
        : ReadAttribute("weighting")
    {
    }

    ~ReadThreadNetworkDiagnosticsWeighting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeWeightingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.Weighting response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics Weighting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsWeighting : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsWeighting()
        : SubscribeAttribute("weighting")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsWeighting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWeightingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.Weighting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DataVersion
 */
class ReadThreadNetworkDiagnosticsDataVersion : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsDataVersion()
        : ReadAttribute("data-version")
    {
    }

    ~ReadThreadNetworkDiagnosticsDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeDataVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.DataVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics DataVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsDataVersion : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsDataVersion()
        : SubscribeAttribute("data-version")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDataVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.DataVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StableDataVersion
 */
class ReadThreadNetworkDiagnosticsStableDataVersion : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsStableDataVersion()
        : ReadAttribute("stable-data-version")
    {
    }

    ~ReadThreadNetworkDiagnosticsStableDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeStableDataVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.StableDataVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics StableDataVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion()
        : SubscribeAttribute("stable-data-version")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStableDataVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.StableDataVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LeaderRouterId
 */
class ReadThreadNetworkDiagnosticsLeaderRouterId : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsLeaderRouterId()
        : ReadAttribute("leader-router-id")
    {
    }

    ~ReadThreadNetworkDiagnosticsLeaderRouterId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeLeaderRouterIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.LeaderRouterId response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics LeaderRouterId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId()
        : SubscribeAttribute("leader-router-id")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLeaderRouterIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.LeaderRouterId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DetachedRoleCount
 */
class ReadThreadNetworkDiagnosticsDetachedRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsDetachedRoleCount()
        : ReadAttribute("detached-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsDetachedRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeDetachedRoleCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.DetachedRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics DetachedRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount()
        : SubscribeAttribute("detached-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDetachedRoleCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.DetachedRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChildRoleCount
 */
class ReadThreadNetworkDiagnosticsChildRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsChildRoleCount()
        : ReadAttribute("child-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsChildRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeChildRoleCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ChildRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ChildRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount()
        : SubscribeAttribute("child-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeChildRoleCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ChildRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RouterRoleCount
 */
class ReadThreadNetworkDiagnosticsRouterRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRouterRoleCount()
        : ReadAttribute("router-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRouterRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRouterRoleCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RouterRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RouterRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount()
        : SubscribeAttribute("router-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRouterRoleCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RouterRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LeaderRoleCount
 */
class ReadThreadNetworkDiagnosticsLeaderRoleCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsLeaderRoleCount()
        : ReadAttribute("leader-role-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsLeaderRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeLeaderRoleCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.LeaderRoleCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics LeaderRoleCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount()
        : SubscribeAttribute("leader-role-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLeaderRoleCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.LeaderRoleCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttachAttemptCount
 */
class ReadThreadNetworkDiagnosticsAttachAttemptCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsAttachAttemptCount()
        : ReadAttribute("attach-attempt-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttachAttemptCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.AttachAttemptCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics AttachAttemptCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount()
        : SubscribeAttribute("attach-attempt-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttachAttemptCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.AttachAttemptCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartitionIdChangeCount
 */
class ReadThreadNetworkDiagnosticsPartitionIdChangeCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPartitionIdChangeCount()
        : ReadAttribute("partition-id-change-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsPartitionIdChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePartitionIdChangeCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PartitionIdChangeCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PartitionIdChangeCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount()
        : SubscribeAttribute("partition-id-change-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePartitionIdChangeCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PartitionIdChangeCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BetterPartitionAttachAttemptCount
 */
class ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount()
        : ReadAttribute("better-partition-attach-attempt-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster
            readAttributeBetterPartitionAttachAttemptCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.BetterPartitionAttachAttemptCount response %@", [value description]);
                if (error != nil) {
                    LogNSError("ThreadNetworkDiagnostics BetterPartitionAttachAttemptCount read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount()
        : SubscribeAttribute("better-partition-attach-attempt-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBetterPartitionAttachAttemptCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.BetterPartitionAttachAttemptCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ParentChangeCount
 */
class ReadThreadNetworkDiagnosticsParentChangeCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsParentChangeCount()
        : ReadAttribute("parent-change-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsParentChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeParentChangeCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ParentChangeCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ParentChangeCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount()
        : SubscribeAttribute("parent-change-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeParentChangeCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ParentChangeCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxTotalCount
 */
class ReadThreadNetworkDiagnosticsTxTotalCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxTotalCount()
        : ReadAttribute("tx-total-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxTotalCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxTotalCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxTotalCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount()
        : SubscribeAttribute("tx-total-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxTotalCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxTotalCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxUnicastCount
 */
class ReadThreadNetworkDiagnosticsTxUnicastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxUnicastCount()
        : ReadAttribute("tx-unicast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxUnicastCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxUnicastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxUnicastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount()
        : SubscribeAttribute("tx-unicast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxUnicastCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxUnicastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxBroadcastCount
 */
class ReadThreadNetworkDiagnosticsTxBroadcastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxBroadcastCount()
        : ReadAttribute("tx-broadcast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxBroadcastCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxBroadcastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxBroadcastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount()
        : SubscribeAttribute("tx-broadcast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxBroadcastCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxBroadcastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxAckRequestedCount
 */
class ReadThreadNetworkDiagnosticsTxAckRequestedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxAckRequestedCount()
        : ReadAttribute("tx-ack-requested-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxAckRequestedCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxAckRequestedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxAckRequestedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount()
        : SubscribeAttribute("tx-ack-requested-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxAckRequestedCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxAckRequestedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxAckedCount
 */
class ReadThreadNetworkDiagnosticsTxAckedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxAckedCount()
        : ReadAttribute("tx-acked-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxAckedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxAckedCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxAckedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxAckedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount()
        : SubscribeAttribute("tx-acked-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxAckedCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxAckedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxNoAckRequestedCount
 */
class ReadThreadNetworkDiagnosticsTxNoAckRequestedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxNoAckRequestedCount()
        : ReadAttribute("tx-no-ack-requested-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxNoAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxNoAckRequestedCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxNoAckRequestedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxNoAckRequestedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount()
        : SubscribeAttribute("tx-no-ack-requested-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxNoAckRequestedCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxNoAckRequestedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxDataCount
 */
class ReadThreadNetworkDiagnosticsTxDataCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxDataCount()
        : ReadAttribute("tx-data-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxDataCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxDataCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxDataCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxDataCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxDataCount()
        : SubscribeAttribute("tx-data-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxDataCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDataCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxDataPollCount
 */
class ReadThreadNetworkDiagnosticsTxDataPollCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxDataPollCount()
        : ReadAttribute("tx-data-poll-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxDataPollCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxDataPollCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxDataPollCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount()
        : SubscribeAttribute("tx-data-poll-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxDataPollCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDataPollCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxBeaconCount
 */
class ReadThreadNetworkDiagnosticsTxBeaconCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxBeaconCount()
        : ReadAttribute("tx-beacon-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxBeaconCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxBeaconCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxBeaconCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount()
        : SubscribeAttribute("tx-beacon-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxBeaconCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxBeaconCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxBeaconRequestCount
 */
class ReadThreadNetworkDiagnosticsTxBeaconRequestCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxBeaconRequestCount()
        : ReadAttribute("tx-beacon-request-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000001F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxBeaconRequestCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxBeaconRequestCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxBeaconRequestCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount()
        : SubscribeAttribute("tx-beacon-request-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000001F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxBeaconRequestCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxBeaconRequestCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxOtherCount
 */
class ReadThreadNetworkDiagnosticsTxOtherCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxOtherCount()
        : ReadAttribute("tx-other-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxOtherCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxOtherCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxOtherCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount()
        : SubscribeAttribute("tx-other-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxOtherCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxOtherCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxRetryCount
 */
class ReadThreadNetworkDiagnosticsTxRetryCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxRetryCount()
        : ReadAttribute("tx-retry-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxRetryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxRetryCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxRetryCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxRetryCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount()
        : SubscribeAttribute("tx-retry-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxRetryCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxRetryCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxDirectMaxRetryExpiryCount
 */
class ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount()
        : ReadAttribute("tx-direct-max-retry-expiry-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxDirectMaxRetryExpiryCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxDirectMaxRetryExpiryCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxDirectMaxRetryExpiryCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount()
        : SubscribeAttribute("tx-direct-max-retry-expiry-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxDirectMaxRetryExpiryCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxDirectMaxRetryExpiryCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxIndirectMaxRetryExpiryCount
 */
class ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount()
        : ReadAttribute("tx-indirect-max-retry-expiry-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxIndirectMaxRetryExpiryCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxIndirectMaxRetryExpiryCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxIndirectMaxRetryExpiryCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount()
        : SubscribeAttribute("tx-indirect-max-retry-expiry-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxIndirectMaxRetryExpiryCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxIndirectMaxRetryExpiryCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrCcaCount
 */
class ReadThreadNetworkDiagnosticsTxErrCcaCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxErrCcaCount()
        : ReadAttribute("tx-err-cca-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxErrCcaCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxErrCcaCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxErrCcaCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxErrCcaCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount()
        : SubscribeAttribute("tx-err-cca-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxErrCcaCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxErrCcaCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrAbortCount
 */
class ReadThreadNetworkDiagnosticsTxErrAbortCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxErrAbortCount()
        : ReadAttribute("tx-err-abort-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxErrAbortCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxErrAbortCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxErrAbortCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxErrAbortCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount()
        : SubscribeAttribute("tx-err-abort-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxErrAbortCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxErrAbortCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrBusyChannelCount
 */
class ReadThreadNetworkDiagnosticsTxErrBusyChannelCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsTxErrBusyChannelCount()
        : ReadAttribute("tx-err-busy-channel-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsTxErrBusyChannelCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxErrBusyChannelCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.TxErrBusyChannelCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics TxErrBusyChannelCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount()
        : SubscribeAttribute("tx-err-busy-channel-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxErrBusyChannelCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.TxErrBusyChannelCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxTotalCount
 */
class ReadThreadNetworkDiagnosticsRxTotalCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxTotalCount()
        : ReadAttribute("rx-total-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxTotalCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxTotalCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxTotalCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount()
        : SubscribeAttribute("rx-total-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxTotalCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxTotalCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxUnicastCount
 */
class ReadThreadNetworkDiagnosticsRxUnicastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxUnicastCount()
        : ReadAttribute("rx-unicast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxUnicastCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxUnicastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxUnicastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount()
        : SubscribeAttribute("rx-unicast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxUnicastCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxUnicastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxBroadcastCount
 */
class ReadThreadNetworkDiagnosticsRxBroadcastCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxBroadcastCount()
        : ReadAttribute("rx-broadcast-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxBroadcastCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxBroadcastCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxBroadcastCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount()
        : SubscribeAttribute("rx-broadcast-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxBroadcastCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxBroadcastCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDataCount
 */
class ReadThreadNetworkDiagnosticsRxDataCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDataCount()
        : ReadAttribute("rx-data-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxDataCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDataCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDataCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDataCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDataCount()
        : SubscribeAttribute("rx-data-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDataCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxDataCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDataCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDataPollCount
 */
class ReadThreadNetworkDiagnosticsRxDataPollCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDataPollCount()
        : ReadAttribute("rx-data-poll-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxDataPollCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDataPollCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDataPollCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount()
        : SubscribeAttribute("rx-data-poll-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxDataPollCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDataPollCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxBeaconCount
 */
class ReadThreadNetworkDiagnosticsRxBeaconCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxBeaconCount()
        : ReadAttribute("rx-beacon-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxBeaconCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxBeaconCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxBeaconCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount()
        : SubscribeAttribute("rx-beacon-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxBeaconCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxBeaconCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxBeaconRequestCount
 */
class ReadThreadNetworkDiagnosticsRxBeaconRequestCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxBeaconRequestCount()
        : ReadAttribute("rx-beacon-request-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxBeaconRequestCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxBeaconRequestCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxBeaconRequestCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount()
        : SubscribeAttribute("rx-beacon-request-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxBeaconRequestCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxBeaconRequestCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxOtherCount
 */
class ReadThreadNetworkDiagnosticsRxOtherCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxOtherCount()
        : ReadAttribute("rx-other-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxOtherCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxOtherCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxOtherCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount()
        : SubscribeAttribute("rx-other-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxOtherCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxOtherCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxAddressFilteredCount
 */
class ReadThreadNetworkDiagnosticsRxAddressFilteredCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxAddressFilteredCount()
        : ReadAttribute("rx-address-filtered-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxAddressFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000002F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxAddressFilteredCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxAddressFilteredCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxAddressFilteredCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount()
        : SubscribeAttribute("rx-address-filtered-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000002F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxAddressFilteredCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxAddressFilteredCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDestAddrFilteredCount
 */
class ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount()
        : ReadAttribute("rx-dest-addr-filtered-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxDestAddrFilteredCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDestAddrFilteredCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDestAddrFilteredCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount()
        : SubscribeAttribute("rx-dest-addr-filtered-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxDestAddrFilteredCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDestAddrFilteredCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxDuplicatedCount
 */
class ReadThreadNetworkDiagnosticsRxDuplicatedCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxDuplicatedCount()
        : ReadAttribute("rx-duplicated-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxDuplicatedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxDuplicatedCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxDuplicatedCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxDuplicatedCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount()
        : SubscribeAttribute("rx-duplicated-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxDuplicatedCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxDuplicatedCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrNoFrameCount
 */
class ReadThreadNetworkDiagnosticsRxErrNoFrameCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrNoFrameCount()
        : ReadAttribute("rx-err-no-frame-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrNoFrameCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxErrNoFrameCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrNoFrameCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrNoFrameCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount()
        : SubscribeAttribute("rx-err-no-frame-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxErrNoFrameCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrNoFrameCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrUnknownNeighborCount
 */
class ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount()
        : ReadAttribute("rx-err-unknown-neighbor-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxErrUnknownNeighborCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrUnknownNeighborCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrUnknownNeighborCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount()
        : SubscribeAttribute("rx-err-unknown-neighbor-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxErrUnknownNeighborCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrUnknownNeighborCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrInvalidSrcAddrCount
 */
class ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount()
        : ReadAttribute("rx-err-invalid-src-addr-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxErrInvalidSrcAddrCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrInvalidSrcAddrCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrInvalidSrcAddrCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount()
        : SubscribeAttribute("rx-err-invalid-src-addr-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxErrInvalidSrcAddrCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrInvalidSrcAddrCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrSecCount
 */
class ReadThreadNetworkDiagnosticsRxErrSecCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrSecCount()
        : ReadAttribute("rx-err-sec-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrSecCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxErrSecCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrSecCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrSecCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount()
        : SubscribeAttribute("rx-err-sec-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxErrSecCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrSecCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrFcsCount
 */
class ReadThreadNetworkDiagnosticsRxErrFcsCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrFcsCount()
        : ReadAttribute("rx-err-fcs-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrFcsCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000036) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxErrFcsCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrFcsCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrFcsCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount()
        : SubscribeAttribute("rx-err-fcs-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxErrFcsCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrFcsCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RxErrOtherCount
 */
class ReadThreadNetworkDiagnosticsRxErrOtherCount : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsRxErrOtherCount()
        : ReadAttribute("rx-err-other-count")
    {
    }

    ~ReadThreadNetworkDiagnosticsRxErrOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000037) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRxErrOtherCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.RxErrOtherCount response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics RxErrOtherCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount()
        : SubscribeAttribute("rx-err-other-count")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRxErrOtherCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.RxErrOtherCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveTimestamp
 */
class ReadThreadNetworkDiagnosticsActiveTimestamp : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsActiveTimestamp()
        : ReadAttribute("active-timestamp")
    {
    }

    ~ReadThreadNetworkDiagnosticsActiveTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000038) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeActiveTimestampWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ActiveTimestamp response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ActiveTimestamp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp()
        : SubscribeAttribute("active-timestamp")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveTimestampWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ActiveTimestamp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PendingTimestamp
 */
class ReadThreadNetworkDiagnosticsPendingTimestamp : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsPendingTimestamp()
        : ReadAttribute("pending-timestamp")
    {
    }

    ~ReadThreadNetworkDiagnosticsPendingTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x00000039) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePendingTimestampWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.PendingTimestamp response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics PendingTimestamp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp()
        : SubscribeAttribute("pending-timestamp")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x00000039) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePendingTimestampWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.PendingTimestamp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Delay
 */
class ReadThreadNetworkDiagnosticsDelay : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsDelay()
        : ReadAttribute("delay")
    {
    }

    ~ReadThreadNetworkDiagnosticsDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeDelayWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.Delay response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics Delay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsDelay : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsDelay()
        : SubscribeAttribute("delay")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.Delay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SecurityPolicy
 */
class ReadThreadNetworkDiagnosticsSecurityPolicy : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsSecurityPolicy()
        : ReadAttribute("security-policy")
    {
    }

    ~ReadThreadNetworkDiagnosticsSecurityPolicy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSecurityPolicyWithCompletion:^(
            MTRThreadNetworkDiagnosticsClusterSecurityPolicy * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.SecurityPolicy response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics SecurityPolicy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy()
        : SubscribeAttribute("security-policy")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSecurityPolicyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRThreadNetworkDiagnosticsClusterSecurityPolicy * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.SecurityPolicy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChannelPage0Mask
 */
class ReadThreadNetworkDiagnosticsChannelPage0Mask : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsChannelPage0Mask()
        : ReadAttribute("channel-page0mask")
    {
    }

    ~ReadThreadNetworkDiagnosticsChannelPage0Mask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeChannelPage0MaskWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ChannelPage0Mask response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ChannelPage0Mask read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsChannelPage0Mask : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsChannelPage0Mask()
        : SubscribeAttribute("channel-page0mask")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsChannelPage0Mask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeChannelPage0MaskWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ChannelPage0Mask response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperationalDatasetComponents
 */
class ReadThreadNetworkDiagnosticsOperationalDatasetComponents : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsOperationalDatasetComponents()
        : ReadAttribute("operational-dataset-components")
    {
    }

    ~ReadThreadNetworkDiagnosticsOperationalDatasetComponents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeOperationalDatasetComponentsWithCompletion:^(
            MTRThreadNetworkDiagnosticsClusterOperationalDatasetComponents * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.OperationalDatasetComponents response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics OperationalDatasetComponents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents()
        : SubscribeAttribute("operational-dataset-components")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOperationalDatasetComponentsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(
                MTRThreadNetworkDiagnosticsClusterOperationalDatasetComponents * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.OperationalDatasetComponents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveNetworkFaultsList
 */
class ReadThreadNetworkDiagnosticsActiveNetworkFaultsList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsActiveNetworkFaultsList()
        : ReadAttribute("active-network-faults-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsActiveNetworkFaultsList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000003E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeActiveNetworkFaultsListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ActiveNetworkFaultsList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ActiveNetworkFaultsList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList()
        : SubscribeAttribute("active-network-faults-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000003E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveNetworkFaultsListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ActiveNetworkFaultsList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadThreadNetworkDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadThreadNetworkDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadThreadNetworkDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadThreadNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadThreadNetworkDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadThreadNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadThreadNetworkDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadThreadNetworkDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadThreadNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThreadNetworkDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ThreadNetworkDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThreadNetworkDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeThreadNetworkDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeThreadNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000035) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThreadNetworkDiagnostics * cluster =
            [[MTRBaseClusterThreadNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThreadNetworkDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WiFiNetworkDiagnostics                                      | 0x0036 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCounts                                                       |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Bssid                                                             | 0x0000 |
| * SecurityType                                                      | 0x0001 |
| * WiFiVersion                                                       | 0x0002 |
| * ChannelNumber                                                     | 0x0003 |
| * Rssi                                                              | 0x0004 |
| * BeaconLostCount                                                   | 0x0005 |
| * BeaconRxCount                                                     | 0x0006 |
| * PacketMulticastRxCount                                            | 0x0007 |
| * PacketMulticastTxCount                                            | 0x0008 |
| * PacketUnicastRxCount                                              | 0x0009 |
| * PacketUnicastTxCount                                              | 0x000A |
| * CurrentMaxRate                                                    | 0x000B |
| * OverrunCount                                                      | 0x000C |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * Disconnection                                                     | 0x0000 |
| * AssociationFailure                                                | 0x0001 |
| * ConnectionStatus                                                  | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCounts
 */
class WiFiNetworkDiagnosticsResetCounts : public ClusterCommand {
public:
    WiFiNetworkDiagnosticsResetCounts()
        : ClusterCommand("reset-counts")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRWiFiNetworkDiagnosticsClusterResetCountsParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster resetCountsWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute Bssid
 */
class ReadWiFiNetworkDiagnosticsBssid : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsBssid()
        : ReadAttribute("bssid")
    {
    }

    ~ReadWiFiNetworkDiagnosticsBssid() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeBssidWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.Bssid response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics Bssid read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsBssid : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsBssid()
        : SubscribeAttribute("bssid")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsBssid() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBssidWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.Bssid response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SecurityType
 */
class ReadWiFiNetworkDiagnosticsSecurityType : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsSecurityType()
        : ReadAttribute("security-type")
    {
    }

    ~ReadWiFiNetworkDiagnosticsSecurityType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSecurityTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.SecurityType response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics SecurityType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsSecurityType : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsSecurityType()
        : SubscribeAttribute("security-type")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsSecurityType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSecurityTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.SecurityType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WiFiVersion
 */
class ReadWiFiNetworkDiagnosticsWiFiVersion : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsWiFiVersion()
        : ReadAttribute("wi-fi-version")
    {
    }

    ~ReadWiFiNetworkDiagnosticsWiFiVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeWiFiVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.WiFiVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics WiFiVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion()
        : SubscribeAttribute("wi-fi-version")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWiFiVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.WiFiVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ChannelNumber
 */
class ReadWiFiNetworkDiagnosticsChannelNumber : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsChannelNumber()
        : ReadAttribute("channel-number")
    {
    }

    ~ReadWiFiNetworkDiagnosticsChannelNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeChannelNumberWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.ChannelNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics ChannelNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber()
        : SubscribeAttribute("channel-number")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeChannelNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.ChannelNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Rssi
 */
class ReadWiFiNetworkDiagnosticsRssi : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsRssi()
        : ReadAttribute("rssi")
    {
    }

    ~ReadWiFiNetworkDiagnosticsRssi() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeRssiWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.Rssi response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics Rssi read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsRssi : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsRssi()
        : SubscribeAttribute("rssi")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsRssi() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRssiWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.Rssi response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BeaconLostCount
 */
class ReadWiFiNetworkDiagnosticsBeaconLostCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsBeaconLostCount()
        : ReadAttribute("beacon-lost-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsBeaconLostCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeBeaconLostCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.BeaconLostCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics BeaconLostCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount()
        : SubscribeAttribute("beacon-lost-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBeaconLostCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.BeaconLostCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BeaconRxCount
 */
class ReadWiFiNetworkDiagnosticsBeaconRxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsBeaconRxCount()
        : ReadAttribute("beacon-rx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsBeaconRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeBeaconRxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.BeaconRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics BeaconRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount()
        : SubscribeAttribute("beacon-rx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBeaconRxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.BeaconRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketMulticastRxCount
 */
class ReadWiFiNetworkDiagnosticsPacketMulticastRxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketMulticastRxCount()
        : ReadAttribute("packet-multicast-rx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketMulticastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePacketMulticastRxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketMulticastRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketMulticastRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount()
        : SubscribeAttribute("packet-multicast-rx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePacketMulticastRxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketMulticastRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketMulticastTxCount
 */
class ReadWiFiNetworkDiagnosticsPacketMulticastTxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketMulticastTxCount()
        : ReadAttribute("packet-multicast-tx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketMulticastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePacketMulticastTxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketMulticastTxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketMulticastTxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount()
        : SubscribeAttribute("packet-multicast-tx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePacketMulticastTxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketMulticastTxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketUnicastRxCount
 */
class ReadWiFiNetworkDiagnosticsPacketUnicastRxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketUnicastRxCount()
        : ReadAttribute("packet-unicast-rx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketUnicastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePacketUnicastRxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketUnicastRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketUnicastRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount()
        : SubscribeAttribute("packet-unicast-rx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePacketUnicastRxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketUnicastRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketUnicastTxCount
 */
class ReadWiFiNetworkDiagnosticsPacketUnicastTxCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsPacketUnicastTxCount()
        : ReadAttribute("packet-unicast-tx-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsPacketUnicastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePacketUnicastTxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.PacketUnicastTxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics PacketUnicastTxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount()
        : SubscribeAttribute("packet-unicast-tx-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePacketUnicastTxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.PacketUnicastTxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentMaxRate
 */
class ReadWiFiNetworkDiagnosticsCurrentMaxRate : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsCurrentMaxRate()
        : ReadAttribute("current-max-rate")
    {
    }

    ~ReadWiFiNetworkDiagnosticsCurrentMaxRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCurrentMaxRateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.CurrentMaxRate response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics CurrentMaxRate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate()
        : SubscribeAttribute("current-max-rate")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentMaxRateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.CurrentMaxRate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverrunCount
 */
class ReadWiFiNetworkDiagnosticsOverrunCount : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsOverrunCount()
        : ReadAttribute("overrun-count")
    {
    }

    ~ReadWiFiNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeOverrunCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.OverrunCount response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics OverrunCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount()
        : SubscribeAttribute("overrun-count")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOverrunCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.OverrunCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadWiFiNetworkDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadWiFiNetworkDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadWiFiNetworkDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadWiFiNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadWiFiNetworkDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadWiFiNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadWiFiNetworkDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadWiFiNetworkDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadWiFiNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WiFiNetworkDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("WiFiNetworkDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000036) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWiFiNetworkDiagnostics * cluster =
            [[MTRBaseClusterWiFiNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WiFiNetworkDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster EthernetNetworkDiagnostics                                  | 0x0037 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ResetCounts                                                       |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * PHYRate                                                           | 0x0000 |
| * FullDuplex                                                        | 0x0001 |
| * PacketRxCount                                                     | 0x0002 |
| * PacketTxCount                                                     | 0x0003 |
| * TxErrCount                                                        | 0x0004 |
| * CollisionCount                                                    | 0x0005 |
| * OverrunCount                                                      | 0x0006 |
| * CarrierDetect                                                     | 0x0007 |
| * TimeSinceReset                                                    | 0x0008 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ResetCounts
 */
class EthernetNetworkDiagnosticsResetCounts : public ClusterCommand {
public:
    EthernetNetworkDiagnosticsResetCounts()
        : ClusterCommand("reset-counts")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTREthernetNetworkDiagnosticsClusterResetCountsParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster resetCountsWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute PHYRate
 */
class ReadEthernetNetworkDiagnosticsPHYRate : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsPHYRate()
        : ReadAttribute("phyrate")
    {
    }

    ~ReadEthernetNetworkDiagnosticsPHYRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePHYRateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.PHYRate response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics PHYRate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsPHYRate : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsPHYRate()
        : SubscribeAttribute("phyrate")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsPHYRate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePHYRateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.PHYRate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FullDuplex
 */
class ReadEthernetNetworkDiagnosticsFullDuplex : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsFullDuplex()
        : ReadAttribute("full-duplex")
    {
    }

    ~ReadEthernetNetworkDiagnosticsFullDuplex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFullDuplexWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.FullDuplex response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics FullDuplex read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex()
        : SubscribeAttribute("full-duplex")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFullDuplexWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.FullDuplex response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketRxCount
 */
class ReadEthernetNetworkDiagnosticsPacketRxCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsPacketRxCount()
        : ReadAttribute("packet-rx-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsPacketRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePacketRxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.PacketRxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics PacketRxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount()
        : SubscribeAttribute("packet-rx-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePacketRxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.PacketRxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PacketTxCount
 */
class ReadEthernetNetworkDiagnosticsPacketTxCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsPacketTxCount()
        : ReadAttribute("packet-tx-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsPacketTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePacketTxCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.PacketTxCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics PacketTxCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount()
        : SubscribeAttribute("packet-tx-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePacketTxCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.PacketTxCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TxErrCount
 */
class ReadEthernetNetworkDiagnosticsTxErrCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsTxErrCount()
        : ReadAttribute("tx-err-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsTxErrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTxErrCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.TxErrCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics TxErrCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount()
        : SubscribeAttribute("tx-err-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTxErrCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.TxErrCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CollisionCount
 */
class ReadEthernetNetworkDiagnosticsCollisionCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsCollisionCount()
        : ReadAttribute("collision-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsCollisionCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCollisionCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.CollisionCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics CollisionCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount()
        : SubscribeAttribute("collision-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCollisionCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.CollisionCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverrunCount
 */
class ReadEthernetNetworkDiagnosticsOverrunCount : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsOverrunCount()
        : ReadAttribute("overrun-count")
    {
    }

    ~ReadEthernetNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeOverrunCountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.OverrunCount response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics OverrunCount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount()
        : SubscribeAttribute("overrun-count")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOverrunCountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.OverrunCount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CarrierDetect
 */
class ReadEthernetNetworkDiagnosticsCarrierDetect : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsCarrierDetect()
        : ReadAttribute("carrier-detect")
    {
    }

    ~ReadEthernetNetworkDiagnosticsCarrierDetect() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCarrierDetectWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.CarrierDetect response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics CarrierDetect read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect()
        : SubscribeAttribute("carrier-detect")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCarrierDetectWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.CarrierDetect response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TimeSinceReset
 */
class ReadEthernetNetworkDiagnosticsTimeSinceReset : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsTimeSinceReset()
        : ReadAttribute("time-since-reset")
    {
    }

    ~ReadEthernetNetworkDiagnosticsTimeSinceReset() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTimeSinceResetWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.TimeSinceReset response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics TimeSinceReset read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset()
        : SubscribeAttribute("time-since-reset")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTimeSinceResetWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.TimeSinceReset response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadEthernetNetworkDiagnosticsGeneratedCommandList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadEthernetNetworkDiagnosticsAcceptedCommandList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadEthernetNetworkDiagnosticsAttributeList : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadEthernetNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadEthernetNetworkDiagnosticsFeatureMap : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadEthernetNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadEthernetNetworkDiagnosticsClusterRevision : public ReadAttribute {
public:
    ReadEthernetNetworkDiagnosticsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadEthernetNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"EthernetNetworkDiagnostics.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("EthernetNetworkDiagnostics ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000037) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterEthernetNetworkDiagnostics * cluster =
            [[MTRBaseClusterEthernetNetworkDiagnostics alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"EthernetNetworkDiagnostics.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BridgedDeviceBasic                                          | 0x0039 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * VendorName                                                        | 0x0001 |
| * VendorID                                                          | 0x0002 |
| * ProductName                                                       | 0x0003 |
| * NodeLabel                                                         | 0x0005 |
| * HardwareVersion                                                   | 0x0007 |
| * HardwareVersionString                                             | 0x0008 |
| * SoftwareVersion                                                   | 0x0009 |
| * SoftwareVersionString                                             | 0x000A |
| * ManufacturingDate                                                 | 0x000B |
| * PartNumber                                                        | 0x000C |
| * ProductURL                                                        | 0x000D |
| * ProductLabel                                                      | 0x000E |
| * SerialNumber                                                      | 0x000F |
| * Reachable                                                         | 0x0011 |
| * UniqueID                                                          | 0x0012 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StartUp                                                           | 0x0000 |
| * ShutDown                                                          | 0x0001 |
| * Leave                                                             | 0x0002 |
| * ReachableChanged                                                  | 0x0003 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute VendorName
 */
class ReadBridgedDeviceBasicVendorName : public ReadAttribute {
public:
    ReadBridgedDeviceBasicVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadBridgedDeviceBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadBridgedDeviceBasicVendorID : public ReadAttribute {
public:
    ReadBridgedDeviceBasicVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadBridgedDeviceBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductName
 */
class ReadBridgedDeviceBasicProductName : public ReadAttribute {
public:
    ReadBridgedDeviceBasicProductName()
        : ReadAttribute("product-name")
    {
    }

    ~ReadBridgedDeviceBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeProductNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ProductName response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ProductName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicProductName : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicProductName()
        : SubscribeAttribute("product-name")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicProductName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ProductName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NodeLabel
 */
class ReadBridgedDeviceBasicNodeLabel : public ReadAttribute {
public:
    ReadBridgedDeviceBasicNodeLabel()
        : ReadAttribute("node-label")
    {
    }

    ~ReadBridgedDeviceBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeNodeLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.NodeLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic NodeLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBridgedDeviceBasicNodeLabel : public WriteAttribute {
public:
    WriteBridgedDeviceBasicNodeLabel()
        : WriteAttribute("node-label")
    {
        AddArgument("attr-name", "node-label");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBridgedDeviceBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeNodeLabelWithValue:value
                                           params:params
                                       completion:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("BridgedDeviceBasic NodeLabel write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBridgedDeviceBasicNodeLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicNodeLabel()
        : SubscribeAttribute("node-label")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicNodeLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNodeLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.NodeLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersion
 */
class ReadBridgedDeviceBasicHardwareVersion : public ReadAttribute {
public:
    ReadBridgedDeviceBasicHardwareVersion()
        : ReadAttribute("hardware-version")
    {
    }

    ~ReadBridgedDeviceBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeHardwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.HardwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic HardwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicHardwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicHardwareVersion()
        : SubscribeAttribute("hardware-version")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicHardwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHardwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.HardwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HardwareVersionString
 */
class ReadBridgedDeviceBasicHardwareVersionString : public ReadAttribute {
public:
    ReadBridgedDeviceBasicHardwareVersionString()
        : ReadAttribute("hardware-version-string")
    {
    }

    ~ReadBridgedDeviceBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeHardwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.HardwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic HardwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicHardwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicHardwareVersionString()
        : SubscribeAttribute("hardware-version-string")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicHardwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHardwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.HardwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersion
 */
class ReadBridgedDeviceBasicSoftwareVersion : public ReadAttribute {
public:
    ReadBridgedDeviceBasicSoftwareVersion()
        : ReadAttribute("software-version")
    {
    }

    ~ReadBridgedDeviceBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeSoftwareVersionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.SoftwareVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic SoftwareVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicSoftwareVersion : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicSoftwareVersion()
        : SubscribeAttribute("software-version")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicSoftwareVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSoftwareVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.SoftwareVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoftwareVersionString
 */
class ReadBridgedDeviceBasicSoftwareVersionString : public ReadAttribute {
public:
    ReadBridgedDeviceBasicSoftwareVersionString()
        : ReadAttribute("software-version-string")
    {
    }

    ~ReadBridgedDeviceBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeSoftwareVersionStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.SoftwareVersionString response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic SoftwareVersionString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicSoftwareVersionString : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicSoftwareVersionString()
        : SubscribeAttribute("software-version-string")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicSoftwareVersionString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSoftwareVersionStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.SoftwareVersionString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ManufacturingDate
 */
class ReadBridgedDeviceBasicManufacturingDate : public ReadAttribute {
public:
    ReadBridgedDeviceBasicManufacturingDate()
        : ReadAttribute("manufacturing-date")
    {
    }

    ~ReadBridgedDeviceBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeManufacturingDateWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ManufacturingDate response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ManufacturingDate read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicManufacturingDate : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicManufacturingDate()
        : SubscribeAttribute("manufacturing-date")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicManufacturingDate() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeManufacturingDateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ManufacturingDate response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PartNumber
 */
class ReadBridgedDeviceBasicPartNumber : public ReadAttribute {
public:
    ReadBridgedDeviceBasicPartNumber()
        : ReadAttribute("part-number")
    {
    }

    ~ReadBridgedDeviceBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributePartNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.PartNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic PartNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicPartNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicPartNumber()
        : SubscribeAttribute("part-number")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicPartNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePartNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.PartNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductURL
 */
class ReadBridgedDeviceBasicProductURL : public ReadAttribute {
public:
    ReadBridgedDeviceBasicProductURL()
        : ReadAttribute("product-url")
    {
    }

    ~ReadBridgedDeviceBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeProductURLWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ProductURL response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ProductURL read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicProductURL : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicProductURL()
        : SubscribeAttribute("product-url")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicProductURL() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductURLWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ProductURL response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductLabel
 */
class ReadBridgedDeviceBasicProductLabel : public ReadAttribute {
public:
    ReadBridgedDeviceBasicProductLabel()
        : ReadAttribute("product-label")
    {
    }

    ~ReadBridgedDeviceBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeProductLabelWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ProductLabel response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ProductLabel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicProductLabel : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicProductLabel()
        : SubscribeAttribute("product-label")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicProductLabel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductLabelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ProductLabel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SerialNumber
 */
class ReadBridgedDeviceBasicSerialNumber : public ReadAttribute {
public:
    ReadBridgedDeviceBasicSerialNumber()
        : ReadAttribute("serial-number")
    {
    }

    ~ReadBridgedDeviceBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeSerialNumberWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.SerialNumber response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic SerialNumber read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicSerialNumber : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicSerialNumber()
        : SubscribeAttribute("serial-number")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicSerialNumber() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSerialNumberWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.SerialNumber response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Reachable
 */
class ReadBridgedDeviceBasicReachable : public ReadAttribute {
public:
    ReadBridgedDeviceBasicReachable()
        : ReadAttribute("reachable")
    {
    }

    ~ReadBridgedDeviceBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeReachableWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.Reachable response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic Reachable read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicReachable : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicReachable()
        : SubscribeAttribute("reachable")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicReachable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReachableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.Reachable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UniqueID
 */
class ReadBridgedDeviceBasicUniqueID : public ReadAttribute {
public:
    ReadBridgedDeviceBasicUniqueID()
        : ReadAttribute("unique-id")
    {
    }

    ~ReadBridgedDeviceBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeUniqueIDWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.UniqueID response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic UniqueID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicUniqueID : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicUniqueID()
        : SubscribeAttribute("unique-id")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicUniqueID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUniqueIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.UniqueID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBridgedDeviceBasicGeneratedCommandList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBridgedDeviceBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBridgedDeviceBasicAcceptedCommandList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBridgedDeviceBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBridgedDeviceBasicAttributeList : public ReadAttribute {
public:
    ReadBridgedDeviceBasicAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBridgedDeviceBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBridgedDeviceBasicFeatureMap : public ReadAttribute {
public:
    ReadBridgedDeviceBasicFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBridgedDeviceBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBridgedDeviceBasicClusterRevision : public ReadAttribute {
public:
    ReadBridgedDeviceBasicClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBridgedDeviceBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BridgedDeviceBasic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BridgedDeviceBasic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBridgedDeviceBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBridgedDeviceBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBridgedDeviceBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000039) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBridgedDeviceBasic * cluster = [[MTRBaseClusterBridgedDeviceBasic alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BridgedDeviceBasic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Switch                                                      | 0x003B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NumberOfPositions                                                 | 0x0000 |
| * CurrentPosition                                                   | 0x0001 |
| * MultiPressMax                                                     | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SwitchLatched                                                     | 0x0000 |
| * InitialPress                                                      | 0x0001 |
| * LongPress                                                         | 0x0002 |
| * ShortRelease                                                      | 0x0003 |
| * LongRelease                                                       | 0x0004 |
| * MultiPressOngoing                                                 | 0x0005 |
| * MultiPressComplete                                                | 0x0006 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute NumberOfPositions
 */
class ReadSwitchNumberOfPositions : public ReadAttribute {
public:
    ReadSwitchNumberOfPositions()
        : ReadAttribute("number-of-positions")
    {
    }

    ~ReadSwitchNumberOfPositions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeNumberOfPositionsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.NumberOfPositions response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch NumberOfPositions read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchNumberOfPositions : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchNumberOfPositions()
        : SubscribeAttribute("number-of-positions")
    {
    }

    ~SubscribeAttributeSwitchNumberOfPositions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfPositionsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.NumberOfPositions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPosition
 */
class ReadSwitchCurrentPosition : public ReadAttribute {
public:
    ReadSwitchCurrentPosition()
        : ReadAttribute("current-position")
    {
    }

    ~ReadSwitchCurrentPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.CurrentPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch CurrentPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchCurrentPosition : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchCurrentPosition()
        : SubscribeAttribute("current-position")
    {
    }

    ~SubscribeAttributeSwitchCurrentPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.CurrentPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MultiPressMax
 */
class ReadSwitchMultiPressMax : public ReadAttribute {
public:
    ReadSwitchMultiPressMax()
        : ReadAttribute("multi-press-max")
    {
    }

    ~ReadSwitchMultiPressMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeMultiPressMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.MultiPressMax response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch MultiPressMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchMultiPressMax : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchMultiPressMax()
        : SubscribeAttribute("multi-press-max")
    {
    }

    ~SubscribeAttributeSwitchMultiPressMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMultiPressMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.MultiPressMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadSwitchGeneratedCommandList : public ReadAttribute {
public:
    ReadSwitchGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadSwitchGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeSwitchGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadSwitchAcceptedCommandList : public ReadAttribute {
public:
    ReadSwitchAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadSwitchAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeSwitchAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadSwitchAttributeList : public ReadAttribute {
public:
    ReadSwitchAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadSwitchAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeSwitchAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadSwitchFeatureMap : public ReadAttribute {
public:
    ReadSwitchFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadSwitchFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeSwitchFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadSwitchClusterRevision : public ReadAttribute {
public:
    ReadSwitchClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadSwitchClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Switch.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Switch ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeSwitchClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeSwitchClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeSwitchClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003B) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterSwitch * cluster = [[MTRBaseClusterSwitch alloc] initWithDevice:device
                                                                           endpointID:@(endpointId)
                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Switch.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AdministratorCommissioning                                  | 0x003C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * OpenCommissioningWindow                                           |   0x00 |
| * OpenBasicCommissioningWindow                                      |   0x01 |
| * RevokeCommissioning                                               |   0x02 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * WindowStatus                                                      | 0x0000 |
| * AdminFabricIndex                                                  | 0x0001 |
| * AdminVendorId                                                     | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command OpenCommissioningWindow
 */
class AdministratorCommissioningOpenCommissioningWindow : public ClusterCommand {
public:
    AdministratorCommissioningOpenCommissioningWindow()
        : ClusterCommand("open-commissioning-window")
    {
        AddArgument("CommissioningTimeout", 0, UINT16_MAX, &mRequest.commissioningTimeout);
        AddArgument("PAKEVerifier", &mRequest.PAKEVerifier);
        AddArgument("Discriminator", 0, UINT16_MAX, &mRequest.discriminator);
        AddArgument("Iterations", 0, UINT32_MAX, &mRequest.iterations);
        AddArgument("Salt", &mRequest.salt);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRAdministratorCommissioningClusterOpenCommissioningWindowParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.commissioningTimeout = [NSNumber numberWithUnsignedShort:mRequest.commissioningTimeout];
        params.pakeVerifier = [NSData dataWithBytes:mRequest.PAKEVerifier.data() length:mRequest.PAKEVerifier.size()];
        params.discriminator = [NSNumber numberWithUnsignedShort:mRequest.discriminator];
        params.iterations = [NSNumber numberWithUnsignedInt:mRequest.iterations];
        params.salt = [NSData dataWithBytes:mRequest.salt.data() length:mRequest.salt.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster openCommissioningWindowWithParams:params
                                            completion:^(NSError * _Nullable error) {
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AdministratorCommissioning::Commands::OpenCommissioningWindow::Type mRequest;
};

/*
 * Command OpenBasicCommissioningWindow
 */
class AdministratorCommissioningOpenBasicCommissioningWindow : public ClusterCommand {
public:
    AdministratorCommissioningOpenBasicCommissioningWindow()
        : ClusterCommand("open-basic-commissioning-window")
    {
        AddArgument("CommissioningTimeout", 0, UINT16_MAX, &mRequest.commissioningTimeout);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRAdministratorCommissioningClusterOpenBasicCommissioningWindowParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.commissioningTimeout = [NSNumber numberWithUnsignedShort:mRequest.commissioningTimeout];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster openBasicCommissioningWindowWithParams:params
                                                 completion:^(NSError * _Nullable error) {
                                                     responsesNeeded--;
                                                     if (error != nil) {
                                                         mError = error;
                                                         LogNSError("Error", error);
                                                     }
                                                     if (responsesNeeded == 0) {
                                                         SetCommandExitStatus(mError);
                                                     }
                                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type mRequest;
};

/*
 * Command RevokeCommissioning
 */
class AdministratorCommissioningRevokeCommissioning : public ClusterCommand {
public:
    AdministratorCommissioningRevokeCommissioning()
        : ClusterCommand("revoke-commissioning")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTRAdministratorCommissioningClusterRevokeCommissioningParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster revokeCommissioningWithParams:params
                                        completion:^(NSError * _Nullable error) {
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute WindowStatus
 */
class ReadAdministratorCommissioningWindowStatus : public ReadAttribute {
public:
    ReadAdministratorCommissioningWindowStatus()
        : ReadAttribute("window-status")
    {
    }

    ~ReadAdministratorCommissioningWindowStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeWindowStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.WindowStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning WindowStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningWindowStatus : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningWindowStatus()
        : SubscribeAttribute("window-status")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningWindowStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWindowStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.WindowStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AdminFabricIndex
 */
class ReadAdministratorCommissioningAdminFabricIndex : public ReadAttribute {
public:
    ReadAdministratorCommissioningAdminFabricIndex()
        : ReadAttribute("admin-fabric-index")
    {
    }

    ~ReadAdministratorCommissioningAdminFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAdminFabricIndexWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AdminFabricIndex response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AdminFabricIndex read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAdminFabricIndex : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAdminFabricIndex()
        : SubscribeAttribute("admin-fabric-index")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAdminFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAdminFabricIndexWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AdminFabricIndex response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AdminVendorId
 */
class ReadAdministratorCommissioningAdminVendorId : public ReadAttribute {
public:
    ReadAdministratorCommissioningAdminVendorId()
        : ReadAttribute("admin-vendor-id")
    {
    }

    ~ReadAdministratorCommissioningAdminVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAdminVendorIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AdminVendorId response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AdminVendorId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAdminVendorId : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAdminVendorId()
        : SubscribeAttribute("admin-vendor-id")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAdminVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAdminVendorIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AdminVendorId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAdministratorCommissioningGeneratedCommandList : public ReadAttribute {
public:
    ReadAdministratorCommissioningGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAdministratorCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAdministratorCommissioningAcceptedCommandList : public ReadAttribute {
public:
    ReadAdministratorCommissioningAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAdministratorCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAdministratorCommissioningAttributeList : public ReadAttribute {
public:
    ReadAdministratorCommissioningAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAdministratorCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAdministratorCommissioningFeatureMap : public ReadAttribute {
public:
    ReadAdministratorCommissioningFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAdministratorCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAdministratorCommissioningClusterRevision : public ReadAttribute {
public:
    ReadAdministratorCommissioningClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAdministratorCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AdministratorCommissioning.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AdministratorCommissioning ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAdministratorCommissioningClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAdministratorCommissioningClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAdministratorCommissioningClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAdministratorCommissioning * cluster =
            [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AdministratorCommissioning.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OperationalCredentials                                      | 0x003E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * AttestationRequest                                                |   0x00 |
| * CertificateChainRequest                                           |   0x02 |
| * CSRRequest                                                        |   0x04 |
| * AddNOC                                                            |   0x06 |
| * UpdateNOC                                                         |   0x07 |
| * UpdateFabricLabel                                                 |   0x09 |
| * RemoveFabric                                                      |   0x0A |
| * AddTrustedRootCertificate                                         |   0x0B |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * NOCs                                                              | 0x0000 |
| * Fabrics                                                           | 0x0001 |
| * SupportedFabrics                                                  | 0x0002 |
| * CommissionedFabrics                                               | 0x0003 |
| * TrustedRootCertificates                                           | 0x0004 |
| * CurrentFabricIndex                                                | 0x0005 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command AttestationRequest
 */
class OperationalCredentialsAttestationRequest : public ClusterCommand {
public:
    OperationalCredentialsAttestationRequest()
        : ClusterCommand("attestation-request")
    {
        AddArgument("AttestationNonce", &mRequest.attestationNonce);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterAttestationRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.attestationNonce = [NSData dataWithBytes:mRequest.attestationNonce.data() length:mRequest.attestationNonce.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster attestationRequestWithParams:params
                                       completion:^(MTROperationalCredentialsClusterAttestationResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::AttestationRequest::Type mRequest;
};

/*
 * Command CertificateChainRequest
 */
class OperationalCredentialsCertificateChainRequest : public ClusterCommand {
public:
    OperationalCredentialsCertificateChainRequest()
        : ClusterCommand("certificate-chain-request")
    {
        AddArgument("CertificateType", 0, UINT8_MAX, &mRequest.certificateType);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterCertificateChainRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.certificateType = [NSNumber numberWithUnsignedChar:mRequest.certificateType];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster certificateChainRequestWithParams:params
                                            completion:^(
                                                MTROperationalCredentialsClusterCertificateChainResponseParams * _Nullable values,
                                                NSError * _Nullable error) {
                                                NSLog(@"Values: %@", values);
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::CertificateChainRequest::Type mRequest;
};

/*
 * Command CSRRequest
 */
class OperationalCredentialsCSRRequest : public ClusterCommand {
public:
    OperationalCredentialsCSRRequest()
        : ClusterCommand("csrrequest")
    {
        AddArgument("CSRNonce", &mRequest.CSRNonce);
        AddArgument("IsForUpdateNOC", 0, 1, &mRequest.isForUpdateNOC);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterCSRRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.csrNonce = [NSData dataWithBytes:mRequest.CSRNonce.data() length:mRequest.CSRNonce.size()];
        if (mRequest.isForUpdateNOC.HasValue()) {
            params.isForUpdateNOC = [NSNumber numberWithBool:mRequest.isForUpdateNOC.Value()];
        } else {
            params.isForUpdateNOC = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster CSRRequestWithParams:params
                               completion:^(MTROperationalCredentialsClusterCSRResponseParams * _Nullable values,
                                   NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::CSRRequest::Type mRequest;
};

/*
 * Command AddNOC
 */
class OperationalCredentialsAddNOC : public ClusterCommand {
public:
    OperationalCredentialsAddNOC()
        : ClusterCommand("add-noc")
    {
        AddArgument("NOCValue", &mRequest.NOCValue);
        AddArgument("ICACValue", &mRequest.ICACValue);
        AddArgument("IPKValue", &mRequest.IPKValue);
        AddArgument("CaseAdminSubject", 0, UINT64_MAX, &mRequest.caseAdminSubject);
        AddArgument("AdminVendorId", 0, UINT16_MAX, &mRequest.adminVendorId);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterAddNOCParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.nocValue = [NSData dataWithBytes:mRequest.NOCValue.data() length:mRequest.NOCValue.size()];
        if (mRequest.ICACValue.HasValue()) {
            params.icacValue = [NSData dataWithBytes:mRequest.ICACValue.Value().data() length:mRequest.ICACValue.Value().size()];
        } else {
            params.icacValue = nil;
        }
        params.ipkValue = [NSData dataWithBytes:mRequest.IPKValue.data() length:mRequest.IPKValue.size()];
        params.caseAdminSubject = [NSNumber numberWithUnsignedLongLong:mRequest.caseAdminSubject];
        params.adminVendorId = [NSNumber numberWithUnsignedShort:chip::to_underlying(mRequest.adminVendorId)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster addNOCWithParams:params
                           completion:^(
                               MTROperationalCredentialsClusterNOCResponseParams * _Nullable values, NSError * _Nullable error) {
                               NSLog(@"Values: %@", values);
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::AddNOC::Type mRequest;
};

/*
 * Command UpdateNOC
 */
class OperationalCredentialsUpdateNOC : public ClusterCommand {
public:
    OperationalCredentialsUpdateNOC()
        : ClusterCommand("update-noc")
    {
        AddArgument("NOCValue", &mRequest.NOCValue);
        AddArgument("ICACValue", &mRequest.ICACValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterUpdateNOCParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.nocValue = [NSData dataWithBytes:mRequest.NOCValue.data() length:mRequest.NOCValue.size()];
        if (mRequest.ICACValue.HasValue()) {
            params.icacValue = [NSData dataWithBytes:mRequest.ICACValue.Value().data() length:mRequest.ICACValue.Value().size()];
        } else {
            params.icacValue = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster updateNOCWithParams:params
                              completion:^(
                                  MTROperationalCredentialsClusterNOCResponseParams * _Nullable values, NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::UpdateNOC::Type mRequest;
};

/*
 * Command UpdateFabricLabel
 */
class OperationalCredentialsUpdateFabricLabel : public ClusterCommand {
public:
    OperationalCredentialsUpdateFabricLabel()
        : ClusterCommand("update-fabric-label")
    {
        AddArgument("Label", &mRequest.label);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterUpdateFabricLabelParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.label = [[NSString alloc] initWithBytes:mRequest.label.data()
                                                length:mRequest.label.size()
                                              encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster updateFabricLabelWithParams:params
                                      completion:^(MTROperationalCredentialsClusterNOCResponseParams * _Nullable values,
                                          NSError * _Nullable error) {
                                          NSLog(@"Values: %@", values);
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::UpdateFabricLabel::Type mRequest;
};

/*
 * Command RemoveFabric
 */
class OperationalCredentialsRemoveFabric : public ClusterCommand {
public:
    OperationalCredentialsRemoveFabric()
        : ClusterCommand("remove-fabric")
    {
        AddArgument("FabricIndex", 0, UINT8_MAX, &mRequest.fabricIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterRemoveFabricParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.fabricIndex = [NSNumber numberWithUnsignedChar:mRequest.fabricIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster removeFabricWithParams:params
                                 completion:^(MTROperationalCredentialsClusterNOCResponseParams * _Nullable values,
                                     NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::RemoveFabric::Type mRequest;
};

/*
 * Command AddTrustedRootCertificate
 */
class OperationalCredentialsAddTrustedRootCertificate : public ClusterCommand {
public:
    OperationalCredentialsAddTrustedRootCertificate()
        : ClusterCommand("add-trusted-root-certificate")
    {
        AddArgument("RootCertificate", &mRequest.rootCertificate);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        __auto_type * params = [[MTROperationalCredentialsClusterAddTrustedRootCertificateParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.rootCertificate = [NSData dataWithBytes:mRequest.rootCertificate.data() length:mRequest.rootCertificate.size()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster addTrustedRootCertificateWithParams:params
                                              completion:^(NSError * _Nullable error) {
                                                  responsesNeeded--;
                                                  if (error != nil) {
                                                      mError = error;
                                                      LogNSError("Error", error);
                                                  }
                                                  if (responsesNeeded == 0) {
                                                      SetCommandExitStatus(mError);
                                                  }
                                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::OperationalCredentials::Commands::AddTrustedRootCertificate::Type mRequest;
};

/*
 * Attribute NOCs
 */
class ReadOperationalCredentialsNOCs : public ReadAttribute {
public:
    ReadOperationalCredentialsNOCs()
        : ReadAttribute("nocs")
    {
    }

    ~ReadOperationalCredentialsNOCs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeNOCsWithParams:params
                                  completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                      NSLog(@"OperationalCredentials.NOCs response %@", [value description]);
                                      if (error != nil) {
                                          LogNSError("OperationalCredentials NOCs read Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsNOCs : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsNOCs()
        : SubscribeAttribute("nocs")
    {
    }

    ~SubscribeAttributeOperationalCredentialsNOCs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNOCsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.NOCs response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Fabrics
 */
class ReadOperationalCredentialsFabrics : public ReadAttribute {
public:
    ReadOperationalCredentialsFabrics()
        : ReadAttribute("fabrics")
    {
    }

    ~ReadOperationalCredentialsFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeFabricsWithParams:params
                                     completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                         NSLog(@"OperationalCredentials.Fabrics response %@", [value description]);
                                         if (error != nil) {
                                             LogNSError("OperationalCredentials Fabrics read Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsFabrics : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsFabrics()
        : SubscribeAttribute("fabrics")
    {
    }

    ~SubscribeAttributeOperationalCredentialsFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFabricsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.Fabrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedFabrics
 */
class ReadOperationalCredentialsSupportedFabrics : public ReadAttribute {
public:
    ReadOperationalCredentialsSupportedFabrics()
        : ReadAttribute("supported-fabrics")
    {
    }

    ~ReadOperationalCredentialsSupportedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSupportedFabricsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.SupportedFabrics response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials SupportedFabrics read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsSupportedFabrics : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsSupportedFabrics()
        : SubscribeAttribute("supported-fabrics")
    {
    }

    ~SubscribeAttributeOperationalCredentialsSupportedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportedFabricsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.SupportedFabrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CommissionedFabrics
 */
class ReadOperationalCredentialsCommissionedFabrics : public ReadAttribute {
public:
    ReadOperationalCredentialsCommissionedFabrics()
        : ReadAttribute("commissioned-fabrics")
    {
    }

    ~ReadOperationalCredentialsCommissionedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCommissionedFabricsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.CommissionedFabrics response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials CommissionedFabrics read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsCommissionedFabrics : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsCommissionedFabrics()
        : SubscribeAttribute("commissioned-fabrics")
    {
    }

    ~SubscribeAttributeOperationalCredentialsCommissionedFabrics() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCommissionedFabricsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.CommissionedFabrics response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TrustedRootCertificates
 */
class ReadOperationalCredentialsTrustedRootCertificates : public ReadAttribute {
public:
    ReadOperationalCredentialsTrustedRootCertificates()
        : ReadAttribute("trusted-root-certificates")
    {
    }

    ~ReadOperationalCredentialsTrustedRootCertificates() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeTrustedRootCertificatesWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.TrustedRootCertificates response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials TrustedRootCertificates read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsTrustedRootCertificates : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsTrustedRootCertificates()
        : SubscribeAttribute("trusted-root-certificates")
    {
    }

    ~SubscribeAttributeOperationalCredentialsTrustedRootCertificates() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTrustedRootCertificatesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.TrustedRootCertificates response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentFabricIndex
 */
class ReadOperationalCredentialsCurrentFabricIndex : public ReadAttribute {
public:
    ReadOperationalCredentialsCurrentFabricIndex()
        : ReadAttribute("current-fabric-index")
    {
    }

    ~ReadOperationalCredentialsCurrentFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCurrentFabricIndexWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.CurrentFabricIndex response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials CurrentFabricIndex read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsCurrentFabricIndex : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsCurrentFabricIndex()
        : SubscribeAttribute("current-fabric-index")
    {
    }

    ~SubscribeAttributeOperationalCredentialsCurrentFabricIndex() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentFabricIndexWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.CurrentFabricIndex response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOperationalCredentialsGeneratedCommandList : public ReadAttribute {
public:
    ReadOperationalCredentialsGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOperationalCredentialsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOperationalCredentialsAcceptedCommandList : public ReadAttribute {
public:
    ReadOperationalCredentialsAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOperationalCredentialsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOperationalCredentialsAttributeList : public ReadAttribute {
public:
    ReadOperationalCredentialsAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOperationalCredentialsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOperationalCredentialsAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOperationalCredentialsFeatureMap : public ReadAttribute {
public:
    ReadOperationalCredentialsFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOperationalCredentialsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOperationalCredentialsFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOperationalCredentialsClusterRevision : public ReadAttribute {
public:
    ReadOperationalCredentialsClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOperationalCredentialsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OperationalCredentials.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OperationalCredentials ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOperationalCredentialsClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOperationalCredentialsClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOperationalCredentialsClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOperationalCredentials * cluster =
            [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OperationalCredentials.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster GroupKeyManagement                                          | 0x003F |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * KeySetWrite                                                       |   0x00 |
| * KeySetRead                                                        |   0x01 |
| * KeySetRemove                                                      |   0x03 |
| * KeySetReadAllIndices                                              |   0x04 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GroupKeyMap                                                       | 0x0000 |
| * GroupTable                                                        | 0x0001 |
| * MaxGroupsPerFabric                                                | 0x0002 |
| * MaxGroupKeysPerFabric                                             | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command KeySetWrite
 */
class GroupKeyManagementKeySetWrite : public ClusterCommand {
public:
    GroupKeyManagementKeySetWrite()
        : ClusterCommand("key-set-write")
        , mComplex_GroupKeySet(&mRequest.groupKeySet)
    {
        AddArgument("GroupKeySet", &mComplex_GroupKeySet);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRGroupKeyManagementClusterKeySetWriteParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupKeySet = [MTRGroupKeyManagementClusterGroupKeySetStruct new];
        params.groupKeySet.groupKeySetID = [NSNumber numberWithUnsignedShort:mRequest.groupKeySet.groupKeySetID];
        params.groupKeySet.groupKeySecurityPolicy =
            [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.groupKeySet.groupKeySecurityPolicy)];
        if (mRequest.groupKeySet.epochKey0.IsNull()) {
            params.groupKeySet.epochKey0 = nil;
        } else {
            params.groupKeySet.epochKey0 = [NSData dataWithBytes:mRequest.groupKeySet.epochKey0.Value().data()
                                                          length:mRequest.groupKeySet.epochKey0.Value().size()];
        }
        if (mRequest.groupKeySet.epochStartTime0.IsNull()) {
            params.groupKeySet.epochStartTime0 = nil;
        } else {
            params.groupKeySet.epochStartTime0 = [NSNumber numberWithUnsignedLongLong:mRequest.groupKeySet.epochStartTime0.Value()];
        }
        if (mRequest.groupKeySet.epochKey1.IsNull()) {
            params.groupKeySet.epochKey1 = nil;
        } else {
            params.groupKeySet.epochKey1 = [NSData dataWithBytes:mRequest.groupKeySet.epochKey1.Value().data()
                                                          length:mRequest.groupKeySet.epochKey1.Value().size()];
        }
        if (mRequest.groupKeySet.epochStartTime1.IsNull()) {
            params.groupKeySet.epochStartTime1 = nil;
        } else {
            params.groupKeySet.epochStartTime1 = [NSNumber numberWithUnsignedLongLong:mRequest.groupKeySet.epochStartTime1.Value()];
        }
        if (mRequest.groupKeySet.epochKey2.IsNull()) {
            params.groupKeySet.epochKey2 = nil;
        } else {
            params.groupKeySet.epochKey2 = [NSData dataWithBytes:mRequest.groupKeySet.epochKey2.Value().data()
                                                          length:mRequest.groupKeySet.epochKey2.Value().size()];
        }
        if (mRequest.groupKeySet.epochStartTime2.IsNull()) {
            params.groupKeySet.epochStartTime2 = nil;
        } else {
            params.groupKeySet.epochStartTime2 = [NSNumber numberWithUnsignedLongLong:mRequest.groupKeySet.epochStartTime2.Value()];
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster keySetWriteWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::GroupKeyManagement::Structs::GroupKeySetStruct::Type> mComplex_GroupKeySet;
};

/*
 * Command KeySetRead
 */
class GroupKeyManagementKeySetRead : public ClusterCommand {
public:
    GroupKeyManagementKeySetRead()
        : ClusterCommand("key-set-read")
    {
        AddArgument("GroupKeySetID", 0, UINT16_MAX, &mRequest.groupKeySetID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRGroupKeyManagementClusterKeySetReadParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupKeySetID = [NSNumber numberWithUnsignedShort:mRequest.groupKeySetID];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster keySetReadWithParams:params
                               completion:^(MTRGroupKeyManagementClusterKeySetReadResponseParams * _Nullable values,
                                   NSError * _Nullable error) {
                                   NSLog(@"Values: %@", values);
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetRead::Type mRequest;
};

/*
 * Command KeySetRemove
 */
class GroupKeyManagementKeySetRemove : public ClusterCommand {
public:
    GroupKeyManagementKeySetRemove()
        : ClusterCommand("key-set-remove")
    {
        AddArgument("GroupKeySetID", 0, UINT16_MAX, &mRequest.groupKeySetID);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRGroupKeyManagementClusterKeySetRemoveParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.groupKeySetID = [NSNumber numberWithUnsignedShort:mRequest.groupKeySetID];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster keySetRemoveWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetRemove::Type mRequest;
};

/*
 * Command KeySetReadAllIndices
 */
class GroupKeyManagementKeySetReadAllIndices : public ClusterCommand {
public:
    GroupKeyManagementKeySetReadAllIndices()
        : ClusterCommand("key-set-read-all-indices")
        , mComplex_GroupKeySetIDs(&mRequest.groupKeySetIDs)
    {
        AddArgument("GroupKeySetIDs", &mComplex_GroupKeySetIDs);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRGroupKeyManagementClusterKeySetReadAllIndicesParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.groupKeySetIDs) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedShort:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.groupKeySetIDs = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                keySetReadAllIndicesWithParams:params
                                    completion:^(MTRGroupKeyManagementClusterKeySetReadAllIndicesResponseParams * _Nullable values,
                                        NSError * _Nullable error) {
                                        NSLog(@"Values: %@", values);
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::GroupKeyManagement::Commands::KeySetReadAllIndices::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint16_t>> mComplex_GroupKeySetIDs;
};

/*
 * Attribute GroupKeyMap
 */
class ReadGroupKeyManagementGroupKeyMap : public ReadAttribute {
public:
    ReadGroupKeyManagementGroupKeyMap()
        : ReadAttribute("group-key-map")
    {
    }

    ~ReadGroupKeyManagementGroupKeyMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeGroupKeyMapWithParams:params
                                         completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                             NSLog(@"GroupKeyManagement.GroupKeyMap response %@", [value description]);
                                             if (error != nil) {
                                                 LogNSError("GroupKeyManagement GroupKeyMap read Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }
};

class WriteGroupKeyManagementGroupKeyMap : public WriteAttribute {
public:
    WriteGroupKeyManagementGroupKeyMap()
        : WriteAttribute("group-key-map")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "group-key-map");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteGroupKeyManagementGroupKeyMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRGroupKeyManagementClusterGroupKeyMapStruct * newElement_0;
                newElement_0 = [MTRGroupKeyManagementClusterGroupKeyMapStruct new];
                newElement_0.groupId = [NSNumber numberWithUnsignedShort:entry_0.groupId];
                newElement_0.groupKeySetID = [NSNumber numberWithUnsignedShort:entry_0.groupKeySetID];
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeGroupKeyMapWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("GroupKeyManagement GroupKeyMap write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::GroupKeyManagement::Structs::GroupKeyMapStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::GroupKeyManagement::Structs::GroupKeyMapStruct::Type>>
        mComplex;
};

class SubscribeAttributeGroupKeyManagementGroupKeyMap : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementGroupKeyMap()
        : SubscribeAttribute("group-key-map")
    {
    }

    ~SubscribeAttributeGroupKeyManagementGroupKeyMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGroupKeyMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.GroupKeyMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GroupTable
 */
class ReadGroupKeyManagementGroupTable : public ReadAttribute {
public:
    ReadGroupKeyManagementGroupTable()
        : ReadAttribute("group-table")
    {
    }

    ~ReadGroupKeyManagementGroupTable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeGroupTableWithParams:params
                                        completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                            NSLog(@"GroupKeyManagement.GroupTable response %@", [value description]);
                                            if (error != nil) {
                                                LogNSError("GroupKeyManagement GroupTable read Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementGroupTable : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementGroupTable()
        : SubscribeAttribute("group-table")
    {
    }

    ~SubscribeAttributeGroupKeyManagementGroupTable() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGroupTableWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.GroupTable response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxGroupsPerFabric
 */
class ReadGroupKeyManagementMaxGroupsPerFabric : public ReadAttribute {
public:
    ReadGroupKeyManagementMaxGroupsPerFabric()
        : ReadAttribute("max-groups-per-fabric")
    {
    }

    ~ReadGroupKeyManagementMaxGroupsPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxGroupsPerFabricWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.MaxGroupsPerFabric response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement MaxGroupsPerFabric read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric()
        : SubscribeAttribute("max-groups-per-fabric")
    {
    }

    ~SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxGroupsPerFabricWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.MaxGroupsPerFabric response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxGroupKeysPerFabric
 */
class ReadGroupKeyManagementMaxGroupKeysPerFabric : public ReadAttribute {
public:
    ReadGroupKeyManagementMaxGroupKeysPerFabric()
        : ReadAttribute("max-group-keys-per-fabric")
    {
    }

    ~ReadGroupKeyManagementMaxGroupKeysPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxGroupKeysPerFabricWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.MaxGroupKeysPerFabric response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement MaxGroupKeysPerFabric read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric()
        : SubscribeAttribute("max-group-keys-per-fabric")
    {
    }

    ~SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxGroupKeysPerFabricWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.MaxGroupKeysPerFabric response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadGroupKeyManagementGeneratedCommandList : public ReadAttribute {
public:
    ReadGroupKeyManagementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadGroupKeyManagementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadGroupKeyManagementAcceptedCommandList : public ReadAttribute {
public:
    ReadGroupKeyManagementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadGroupKeyManagementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadGroupKeyManagementAttributeList : public ReadAttribute {
public:
    ReadGroupKeyManagementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadGroupKeyManagementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeGroupKeyManagementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadGroupKeyManagementFeatureMap : public ReadAttribute {
public:
    ReadGroupKeyManagementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadGroupKeyManagementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeGroupKeyManagementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadGroupKeyManagementClusterRevision : public ReadAttribute {
public:
    ReadGroupKeyManagementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadGroupKeyManagementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"GroupKeyManagement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("GroupKeyManagement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeGroupKeyManagementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeGroupKeyManagementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeGroupKeyManagementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000003F) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterGroupKeyManagement * cluster = [[MTRBaseClusterGroupKeyManagement alloc] initWithDevice:device
                                                                                                   endpointID:@(endpointId)
                                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"GroupKeyManagement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FixedLabel                                                  | 0x0040 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LabelList                                                         | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute LabelList
 */
class ReadFixedLabelLabelList : public ReadAttribute {
public:
    ReadFixedLabelLabelList()
        : ReadAttribute("label-list")
    {
    }

    ~ReadFixedLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeLabelListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.LabelList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel LabelList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelLabelList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelLabelList()
        : SubscribeAttribute("label-list")
    {
    }

    ~SubscribeAttributeFixedLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLabelListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.LabelList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadFixedLabelGeneratedCommandList : public ReadAttribute {
public:
    ReadFixedLabelGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadFixedLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeFixedLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadFixedLabelAcceptedCommandList : public ReadAttribute {
public:
    ReadFixedLabelAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadFixedLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeFixedLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadFixedLabelAttributeList : public ReadAttribute {
public:
    ReadFixedLabelAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadFixedLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeFixedLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadFixedLabelFeatureMap : public ReadAttribute {
public:
    ReadFixedLabelFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadFixedLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeFixedLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadFixedLabelClusterRevision : public ReadAttribute {
public:
    ReadFixedLabelClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadFixedLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FixedLabel.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("FixedLabel ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFixedLabelClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeFixedLabelClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeFixedLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000040) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFixedLabel * cluster = [[MTRBaseClusterFixedLabel alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FixedLabel.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster UserLabel                                                   | 0x0041 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LabelList                                                         | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute LabelList
 */
class ReadUserLabelLabelList : public ReadAttribute {
public:
    ReadUserLabelLabelList()
        : ReadAttribute("label-list")
    {
    }

    ~ReadUserLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeLabelListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.LabelList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel LabelList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteUserLabelLabelList : public WriteAttribute {
public:
    WriteUserLabelLabelList()
        : WriteAttribute("label-list")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "label-list");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteUserLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRUserLabelClusterLabelStruct * newElement_0;
                newElement_0 = [MTRUserLabelClusterLabelStruct new];
                newElement_0.label = [[NSString alloc] initWithBytes:entry_0.label.data()
                                                              length:entry_0.label.size()
                                                            encoding:NSUTF8StringEncoding];
                newElement_0.value = [[NSString alloc] initWithBytes:entry_0.value.data()
                                                              length:entry_0.value.size()
                                                            encoding:NSUTF8StringEncoding];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeLabelListWithValue:value
                                           params:params
                                       completion:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("UserLabel LabelList write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::UserLabel::Structs::LabelStruct::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::UserLabel::Structs::LabelStruct::Type>> mComplex;
};

class SubscribeAttributeUserLabelLabelList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelLabelList()
        : SubscribeAttribute("label-list")
    {
    }

    ~SubscribeAttributeUserLabelLabelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLabelListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.LabelList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadUserLabelGeneratedCommandList : public ReadAttribute {
public:
    ReadUserLabelGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadUserLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeUserLabelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadUserLabelAcceptedCommandList : public ReadAttribute {
public:
    ReadUserLabelAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadUserLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeUserLabelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadUserLabelAttributeList : public ReadAttribute {
public:
    ReadUserLabelAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadUserLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeUserLabelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadUserLabelFeatureMap : public ReadAttribute {
public:
    ReadUserLabelFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadUserLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeUserLabelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadUserLabelClusterRevision : public ReadAttribute {
public:
    ReadUserLabelClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadUserLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"UserLabel.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("UserLabel ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeUserLabelClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeUserLabelClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeUserLabelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000041) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterUserLabel * cluster = [[MTRBaseClusterUserLabel alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"UserLabel.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BooleanState                                                | 0x0045 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * StateValue                                                        | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * StateChange                                                       | 0x0000 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute StateValue
 */
class ReadBooleanStateStateValue : public ReadAttribute {
public:
    ReadBooleanStateStateValue()
        : ReadAttribute("state-value")
    {
    }

    ~ReadBooleanStateStateValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeStateValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.StateValue response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState StateValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateStateValue : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateStateValue()
        : SubscribeAttribute("state-value")
    {
    }

    ~SubscribeAttributeBooleanStateStateValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStateValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.StateValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBooleanStateGeneratedCommandList : public ReadAttribute {
public:
    ReadBooleanStateGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBooleanStateGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBooleanStateGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBooleanStateAcceptedCommandList : public ReadAttribute {
public:
    ReadBooleanStateAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBooleanStateAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBooleanStateAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBooleanStateAttributeList : public ReadAttribute {
public:
    ReadBooleanStateAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBooleanStateAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBooleanStateAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBooleanStateFeatureMap : public ReadAttribute {
public:
    ReadBooleanStateFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBooleanStateFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBooleanStateFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBooleanStateClusterRevision : public ReadAttribute {
public:
    ReadBooleanStateClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBooleanStateClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BooleanState.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BooleanState ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBooleanStateClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBooleanStateClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBooleanStateClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000045) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBooleanState * cluster = [[MTRBaseClusterBooleanState alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BooleanState.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ModeSelect                                                  | 0x0050 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ChangeToMode                                                      |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Description                                                       | 0x0000 |
| * StandardNamespace                                                 | 0x0001 |
| * SupportedModes                                                    | 0x0002 |
| * CurrentMode                                                       | 0x0003 |
| * StartUpMode                                                       | 0x0004 |
| * OnMode                                                            | 0x0005 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ChangeToMode
 */
class ModeSelectChangeToMode : public ClusterCommand {
public:
    ModeSelectChangeToMode()
        : ClusterCommand("change-to-mode")
    {
        AddArgument("NewMode", 0, UINT8_MAX, &mRequest.newMode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRModeSelectClusterChangeToModeParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.newMode = [NSNumber numberWithUnsignedChar:mRequest.newMode];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster changeToModeWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ModeSelect::Commands::ChangeToMode::Type mRequest;
};

/*
 * Attribute Description
 */
class ReadModeSelectDescription : public ReadAttribute {
public:
    ReadModeSelectDescription()
        : ReadAttribute("description")
    {
    }

    ~ReadModeSelectDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeDescriptionWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.Description response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect Description read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectDescription : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectDescription()
        : SubscribeAttribute("description")
    {
    }

    ~SubscribeAttributeModeSelectDescription() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDescriptionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.Description response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StandardNamespace
 */
class ReadModeSelectStandardNamespace : public ReadAttribute {
public:
    ReadModeSelectStandardNamespace()
        : ReadAttribute("standard-namespace")
    {
    }

    ~ReadModeSelectStandardNamespace() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeStandardNamespaceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.StandardNamespace response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect StandardNamespace read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectStandardNamespace : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectStandardNamespace()
        : SubscribeAttribute("standard-namespace")
    {
    }

    ~SubscribeAttributeModeSelectStandardNamespace() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStandardNamespaceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.StandardNamespace response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedModes
 */
class ReadModeSelectSupportedModes : public ReadAttribute {
public:
    ReadModeSelectSupportedModes()
        : ReadAttribute("supported-modes")
    {
    }

    ~ReadModeSelectSupportedModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSupportedModesWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.SupportedModes response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect SupportedModes read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectSupportedModes : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectSupportedModes()
        : SubscribeAttribute("supported-modes")
    {
    }

    ~SubscribeAttributeModeSelectSupportedModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportedModesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.SupportedModes response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentMode
 */
class ReadModeSelectCurrentMode : public ReadAttribute {
public:
    ReadModeSelectCurrentMode()
        : ReadAttribute("current-mode")
    {
    }

    ~ReadModeSelectCurrentMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeCurrentModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.CurrentMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect CurrentMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectCurrentMode : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectCurrentMode()
        : SubscribeAttribute("current-mode")
    {
    }

    ~SubscribeAttributeModeSelectCurrentMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.CurrentMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartUpMode
 */
class ReadModeSelectStartUpMode : public ReadAttribute {
public:
    ReadModeSelectStartUpMode()
        : ReadAttribute("start-up-mode")
    {
    }

    ~ReadModeSelectStartUpMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeStartUpModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.StartUpMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect StartUpMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteModeSelectStartUpMode : public WriteAttribute {
public:
    WriteModeSelectStartUpMode()
        : WriteAttribute("start-up-mode")
    {
        AddArgument("attr-name", "start-up-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteModeSelectStartUpMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeStartUpModeWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("ModeSelect StartUpMode write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeModeSelectStartUpMode : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectStartUpMode()
        : SubscribeAttribute("start-up-mode")
    {
    }

    ~SubscribeAttributeModeSelectStartUpMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStartUpModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.StartUpMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OnMode
 */
class ReadModeSelectOnMode : public ReadAttribute {
public:
    ReadModeSelectOnMode()
        : ReadAttribute("on-mode")
    {
    }

    ~ReadModeSelectOnMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOnModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.OnMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect OnMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteModeSelectOnMode : public WriteAttribute {
public:
    WriteModeSelectOnMode()
        : WriteAttribute("on-mode")
    {
        AddArgument("attr-name", "on-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteModeSelectOnMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOnModeWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("ModeSelect OnMode write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeModeSelectOnMode : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectOnMode()
        : SubscribeAttribute("on-mode")
    {
    }

    ~SubscribeAttributeModeSelectOnMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOnModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.OnMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadModeSelectGeneratedCommandList : public ReadAttribute {
public:
    ReadModeSelectGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadModeSelectGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeModeSelectGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadModeSelectAcceptedCommandList : public ReadAttribute {
public:
    ReadModeSelectAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadModeSelectAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeModeSelectAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadModeSelectAttributeList : public ReadAttribute {
public:
    ReadModeSelectAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadModeSelectAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeModeSelectAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadModeSelectFeatureMap : public ReadAttribute {
public:
    ReadModeSelectFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadModeSelectFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeModeSelectFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadModeSelectClusterRevision : public ReadAttribute {
public:
    ReadModeSelectClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadModeSelectClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ModeSelect.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ModeSelect ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeModeSelectClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeModeSelectClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeModeSelectClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000050) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterModeSelect * cluster = [[MTRBaseClusterModeSelect alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ModeSelect.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster DoorLock                                                    | 0x0101 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * LockDoor                                                          |   0x00 |
| * UnlockDoor                                                        |   0x01 |
| * UnlockWithTimeout                                                 |   0x03 |
| * SetWeekDaySchedule                                                |   0x0B |
| * GetWeekDaySchedule                                                |   0x0C |
| * ClearWeekDaySchedule                                              |   0x0D |
| * SetYearDaySchedule                                                |   0x0E |
| * GetYearDaySchedule                                                |   0x0F |
| * ClearYearDaySchedule                                              |   0x10 |
| * SetHolidaySchedule                                                |   0x11 |
| * GetHolidaySchedule                                                |   0x12 |
| * ClearHolidaySchedule                                              |   0x13 |
| * SetUser                                                           |   0x1A |
| * GetUser                                                           |   0x1B |
| * ClearUser                                                         |   0x1D |
| * SetCredential                                                     |   0x22 |
| * GetCredentialStatus                                               |   0x24 |
| * ClearCredential                                                   |   0x26 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LockState                                                         | 0x0000 |
| * LockType                                                          | 0x0001 |
| * ActuatorEnabled                                                   | 0x0002 |
| * DoorState                                                         | 0x0003 |
| * DoorOpenEvents                                                    | 0x0004 |
| * DoorClosedEvents                                                  | 0x0005 |
| * OpenPeriod                                                        | 0x0006 |
| * NumberOfTotalUsersSupported                                       | 0x0011 |
| * NumberOfPINUsersSupported                                         | 0x0012 |
| * NumberOfRFIDUsersSupported                                        | 0x0013 |
| * NumberOfWeekDaySchedulesSupportedPerUser                          | 0x0014 |
| * NumberOfYearDaySchedulesSupportedPerUser                          | 0x0015 |
| * NumberOfHolidaySchedulesSupported                                 | 0x0016 |
| * MaxPINCodeLength                                                  | 0x0017 |
| * MinPINCodeLength                                                  | 0x0018 |
| * MaxRFIDCodeLength                                                 | 0x0019 |
| * MinRFIDCodeLength                                                 | 0x001A |
| * CredentialRulesSupport                                            | 0x001B |
| * NumberOfCredentialsSupportedPerUser                               | 0x001C |
| * Language                                                          | 0x0021 |
| * LEDSettings                                                       | 0x0022 |
| * AutoRelockTime                                                    | 0x0023 |
| * SoundVolume                                                       | 0x0024 |
| * OperatingMode                                                     | 0x0025 |
| * SupportedOperatingModes                                           | 0x0026 |
| * DefaultConfigurationRegister                                      | 0x0027 |
| * EnableLocalProgramming                                            | 0x0028 |
| * EnableOneTouchLocking                                             | 0x0029 |
| * EnableInsideStatusLED                                             | 0x002A |
| * EnablePrivacyModeButton                                           | 0x002B |
| * LocalProgrammingFeatures                                          | 0x002C |
| * WrongCodeEntryLimit                                               | 0x0030 |
| * UserCodeTemporaryDisableTime                                      | 0x0031 |
| * SendPINOverTheAir                                                 | 0x0032 |
| * RequirePINforRemoteOperation                                      | 0x0033 |
| * ExpiringUserTimeout                                               | 0x0035 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * DoorLockAlarm                                                     | 0x0000 |
| * DoorStateChange                                                   | 0x0001 |
| * LockOperation                                                     | 0x0002 |
| * LockOperationError                                                | 0x0003 |
| * LockUserChange                                                    | 0x0004 |
\*----------------------------------------------------------------------------*/

/*
 * Command LockDoor
 */
class DoorLockLockDoor : public ClusterCommand {
public:
    DoorLockLockDoor()
        : ClusterCommand("lock-door")
    {
        AddArgument("PinCode", &mRequest.pinCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterLockDoorParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.pinCode.HasValue()) {
            params.pinCode = [NSData dataWithBytes:mRequest.pinCode.Value().data() length:mRequest.pinCode.Value().size()];
        } else {
            params.pinCode = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster lockDoorWithParams:params
                             completion:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::LockDoor::Type mRequest;
};

/*
 * Command UnlockDoor
 */
class DoorLockUnlockDoor : public ClusterCommand {
public:
    DoorLockUnlockDoor()
        : ClusterCommand("unlock-door")
    {
        AddArgument("PinCode", &mRequest.pinCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterUnlockDoorParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.pinCode.HasValue()) {
            params.pinCode = [NSData dataWithBytes:mRequest.pinCode.Value().data() length:mRequest.pinCode.Value().size()];
        } else {
            params.pinCode = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster unlockDoorWithParams:params
                               completion:^(NSError * _Nullable error) {
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::UnlockDoor::Type mRequest;
};

/*
 * Command UnlockWithTimeout
 */
class DoorLockUnlockWithTimeout : public ClusterCommand {
public:
    DoorLockUnlockWithTimeout()
        : ClusterCommand("unlock-with-timeout")
    {
        AddArgument("Timeout", 0, UINT16_MAX, &mRequest.timeout);
        AddArgument("PinCode", &mRequest.pinCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterUnlockWithTimeoutParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.timeout = [NSNumber numberWithUnsignedShort:mRequest.timeout];
        if (mRequest.pinCode.HasValue()) {
            params.pinCode = [NSData dataWithBytes:mRequest.pinCode.Value().data() length:mRequest.pinCode.Value().size()];
        } else {
            params.pinCode = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster unlockWithTimeoutWithParams:params
                                      completion:^(NSError * _Nullable error) {
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::UnlockWithTimeout::Type mRequest;
};

/*
 * Command SetWeekDaySchedule
 */
class DoorLockSetWeekDaySchedule : public ClusterCommand {
public:
    DoorLockSetWeekDaySchedule()
        : ClusterCommand("set-week-day-schedule")
    {
        AddArgument("WeekDayIndex", 0, UINT8_MAX, &mRequest.weekDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("DaysMask", 0, UINT8_MAX, &mRequest.daysMask);
        AddArgument("StartHour", 0, UINT8_MAX, &mRequest.startHour);
        AddArgument("StartMinute", 0, UINT8_MAX, &mRequest.startMinute);
        AddArgument("EndHour", 0, UINT8_MAX, &mRequest.endHour);
        AddArgument("EndMinute", 0, UINT8_MAX, &mRequest.endMinute);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterSetWeekDayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.weekDayIndex = [NSNumber numberWithUnsignedChar:mRequest.weekDayIndex];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        params.daysMask = [NSNumber numberWithUnsignedChar:mRequest.daysMask.Raw()];
        params.startHour = [NSNumber numberWithUnsignedChar:mRequest.startHour];
        params.startMinute = [NSNumber numberWithUnsignedChar:mRequest.startMinute];
        params.endHour = [NSNumber numberWithUnsignedChar:mRequest.endHour];
        params.endMinute = [NSNumber numberWithUnsignedChar:mRequest.endMinute];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setWeekDayScheduleWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetWeekDaySchedule::Type mRequest;
};

/*
 * Command GetWeekDaySchedule
 */
class DoorLockGetWeekDaySchedule : public ClusterCommand {
public:
    DoorLockGetWeekDaySchedule()
        : ClusterCommand("get-week-day-schedule")
    {
        AddArgument("WeekDayIndex", 0, UINT8_MAX, &mRequest.weekDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterGetWeekDayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.weekDayIndex = [NSNumber numberWithUnsignedChar:mRequest.weekDayIndex];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getWeekDayScheduleWithParams:params
                                       completion:^(MTRDoorLockClusterGetWeekDayScheduleResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetWeekDaySchedule::Type mRequest;
};

/*
 * Command ClearWeekDaySchedule
 */
class DoorLockClearWeekDaySchedule : public ClusterCommand {
public:
    DoorLockClearWeekDaySchedule()
        : ClusterCommand("clear-week-day-schedule")
    {
        AddArgument("WeekDayIndex", 0, UINT8_MAX, &mRequest.weekDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterClearWeekDayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.weekDayIndex = [NSNumber numberWithUnsignedChar:mRequest.weekDayIndex];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearWeekDayScheduleWithParams:params
                                         completion:^(NSError * _Nullable error) {
                                             responsesNeeded--;
                                             if (error != nil) {
                                                 mError = error;
                                                 LogNSError("Error", error);
                                             }
                                             if (responsesNeeded == 0) {
                                                 SetCommandExitStatus(mError);
                                             }
                                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearWeekDaySchedule::Type mRequest;
};

/*
 * Command SetYearDaySchedule
 */
class DoorLockSetYearDaySchedule : public ClusterCommand {
public:
    DoorLockSetYearDaySchedule()
        : ClusterCommand("set-year-day-schedule")
    {
        AddArgument("YearDayIndex", 0, UINT8_MAX, &mRequest.yearDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("LocalStartTime", 0, UINT32_MAX, &mRequest.localStartTime);
        AddArgument("LocalEndTime", 0, UINT32_MAX, &mRequest.localEndTime);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterSetYearDayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.yearDayIndex = [NSNumber numberWithUnsignedChar:mRequest.yearDayIndex];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        params.localStartTime = [NSNumber numberWithUnsignedInt:mRequest.localStartTime];
        params.localEndTime = [NSNumber numberWithUnsignedInt:mRequest.localEndTime];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setYearDayScheduleWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetYearDaySchedule::Type mRequest;
};

/*
 * Command GetYearDaySchedule
 */
class DoorLockGetYearDaySchedule : public ClusterCommand {
public:
    DoorLockGetYearDaySchedule()
        : ClusterCommand("get-year-day-schedule")
    {
        AddArgument("YearDayIndex", 0, UINT8_MAX, &mRequest.yearDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterGetYearDayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.yearDayIndex = [NSNumber numberWithUnsignedChar:mRequest.yearDayIndex];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getYearDayScheduleWithParams:params
                                       completion:^(MTRDoorLockClusterGetYearDayScheduleResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetYearDaySchedule::Type mRequest;
};

/*
 * Command ClearYearDaySchedule
 */
class DoorLockClearYearDaySchedule : public ClusterCommand {
public:
    DoorLockClearYearDaySchedule()
        : ClusterCommand("clear-year-day-schedule")
    {
        AddArgument("YearDayIndex", 0, UINT8_MAX, &mRequest.yearDayIndex);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterClearYearDayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.yearDayIndex = [NSNumber numberWithUnsignedChar:mRequest.yearDayIndex];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearYearDayScheduleWithParams:params
                                         completion:^(NSError * _Nullable error) {
                                             responsesNeeded--;
                                             if (error != nil) {
                                                 mError = error;
                                                 LogNSError("Error", error);
                                             }
                                             if (responsesNeeded == 0) {
                                                 SetCommandExitStatus(mError);
                                             }
                                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearYearDaySchedule::Type mRequest;
};

/*
 * Command SetHolidaySchedule
 */
class DoorLockSetHolidaySchedule : public ClusterCommand {
public:
    DoorLockSetHolidaySchedule()
        : ClusterCommand("set-holiday-schedule")
    {
        AddArgument("HolidayIndex", 0, UINT8_MAX, &mRequest.holidayIndex);
        AddArgument("LocalStartTime", 0, UINT32_MAX, &mRequest.localStartTime);
        AddArgument("LocalEndTime", 0, UINT32_MAX, &mRequest.localEndTime);
        AddArgument("OperatingMode", 0, UINT8_MAX, &mRequest.operatingMode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterSetHolidayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.holidayIndex = [NSNumber numberWithUnsignedChar:mRequest.holidayIndex];
        params.localStartTime = [NSNumber numberWithUnsignedInt:mRequest.localStartTime];
        params.localEndTime = [NSNumber numberWithUnsignedInt:mRequest.localEndTime];
        params.operatingMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.operatingMode)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setHolidayScheduleWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetHolidaySchedule::Type mRequest;
};

/*
 * Command GetHolidaySchedule
 */
class DoorLockGetHolidaySchedule : public ClusterCommand {
public:
    DoorLockGetHolidaySchedule()
        : ClusterCommand("get-holiday-schedule")
    {
        AddArgument("HolidayIndex", 0, UINT8_MAX, &mRequest.holidayIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterGetHolidayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.holidayIndex = [NSNumber numberWithUnsignedChar:mRequest.holidayIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getHolidayScheduleWithParams:params
                                       completion:^(MTRDoorLockClusterGetHolidayScheduleResponseParams * _Nullable values,
                                           NSError * _Nullable error) {
                                           NSLog(@"Values: %@", values);
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetHolidaySchedule::Type mRequest;
};

/*
 * Command ClearHolidaySchedule
 */
class DoorLockClearHolidaySchedule : public ClusterCommand {
public:
    DoorLockClearHolidaySchedule()
        : ClusterCommand("clear-holiday-schedule")
    {
        AddArgument("HolidayIndex", 0, UINT8_MAX, &mRequest.holidayIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterClearHolidayScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.holidayIndex = [NSNumber numberWithUnsignedChar:mRequest.holidayIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearHolidayScheduleWithParams:params
                                         completion:^(NSError * _Nullable error) {
                                             responsesNeeded--;
                                             if (error != nil) {
                                                 mError = error;
                                                 LogNSError("Error", error);
                                             }
                                             if (responsesNeeded == 0) {
                                                 SetCommandExitStatus(mError);
                                             }
                                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearHolidaySchedule::Type mRequest;
};

/*
 * Command SetUser
 */
class DoorLockSetUser : public ClusterCommand {
public:
    DoorLockSetUser()
        : ClusterCommand("set-user")
    {
        AddArgument("OperationType", 0, UINT8_MAX, &mRequest.operationType);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("UserName", &mRequest.userName);
        AddArgument("UserUniqueId", 0, UINT32_MAX, &mRequest.userUniqueId);
        AddArgument("UserStatus", 0, UINT8_MAX, &mRequest.userStatus);
        AddArgument("UserType", 0, UINT8_MAX, &mRequest.userType);
        AddArgument("CredentialRule", 0, UINT8_MAX, &mRequest.credentialRule);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterSetUserParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.operationType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.operationType)];
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        if (mRequest.userName.IsNull()) {
            params.userName = nil;
        } else {
            params.userName = [[NSString alloc] initWithBytes:mRequest.userName.Value().data()
                                                       length:mRequest.userName.Value().size()
                                                     encoding:NSUTF8StringEncoding];
        }
        if (mRequest.userUniqueId.IsNull()) {
            params.userUniqueId = nil;
        } else {
            params.userUniqueId = [NSNumber numberWithUnsignedInt:mRequest.userUniqueId.Value()];
        }
        if (mRequest.userStatus.IsNull()) {
            params.userStatus = nil;
        } else {
            params.userStatus = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.userStatus.Value())];
        }
        if (mRequest.userType.IsNull()) {
            params.userType = nil;
        } else {
            params.userType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.userType.Value())];
        }
        if (mRequest.credentialRule.IsNull()) {
            params.credentialRule = nil;
        } else {
            params.credentialRule = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credentialRule.Value())];
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setUserWithParams:params
                            completion:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetUser::Type mRequest;
};

/*
 * Command GetUser
 */
class DoorLockGetUser : public ClusterCommand {
public:
    DoorLockGetUser()
        : ClusterCommand("get-user")
    {
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterGetUserParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getUserWithParams:params
                            completion:^(MTRDoorLockClusterGetUserResponseParams * _Nullable values, NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetUser::Type mRequest;
};

/*
 * Command ClearUser
 */
class DoorLockClearUser : public ClusterCommand {
public:
    DoorLockClearUser()
        : ClusterCommand("clear-user")
    {
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterClearUserParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearUserWithParams:params
                              completion:^(NSError * _Nullable error) {
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearUser::Type mRequest;
};

/*
 * Command SetCredential
 */
class DoorLockSetCredential : public ClusterCommand {
public:
    DoorLockSetCredential()
        : ClusterCommand("set-credential")
        , mComplex_Credential(&mRequest.credential)
    {
        AddArgument("OperationType", 0, UINT8_MAX, &mRequest.operationType);
        AddArgument("Credential", &mComplex_Credential);
        AddArgument("CredentialData", &mRequest.credentialData);
        AddArgument("UserIndex", 0, UINT16_MAX, &mRequest.userIndex);
        AddArgument("UserStatus", 0, UINT8_MAX, &mRequest.userStatus);
        AddArgument("UserType", 0, UINT8_MAX, &mRequest.userType);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterSetCredentialParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.operationType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.operationType)];
        params.credential = [MTRDoorLockClusterDlCredential new];
        params.credential.credentialType =
            [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credential.credentialType)];
        params.credential.credentialIndex = [NSNumber numberWithUnsignedShort:mRequest.credential.credentialIndex];
        params.credentialData = [NSData dataWithBytes:mRequest.credentialData.data() length:mRequest.credentialData.size()];
        if (mRequest.userIndex.IsNull()) {
            params.userIndex = nil;
        } else {
            params.userIndex = [NSNumber numberWithUnsignedShort:mRequest.userIndex.Value()];
        }
        if (mRequest.userStatus.IsNull()) {
            params.userStatus = nil;
        } else {
            params.userStatus = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.userStatus.Value())];
        }
        if (mRequest.userType.IsNull()) {
            params.userType = nil;
        } else {
            params.userType = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.userType.Value())];
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setCredentialWithParams:params
                                  completion:^(
                                      MTRDoorLockClusterSetCredentialResponseParams * _Nullable values, NSError * _Nullable error) {
                                      NSLog(@"Values: %@", values);
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::SetCredential::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::DoorLock::Structs::DlCredential::Type> mComplex_Credential;
};

/*
 * Command GetCredentialStatus
 */
class DoorLockGetCredentialStatus : public ClusterCommand {
public:
    DoorLockGetCredentialStatus()
        : ClusterCommand("get-credential-status")
        , mComplex_Credential(&mRequest.credential)
    {
        AddArgument("Credential", &mComplex_Credential);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterGetCredentialStatusParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.credential = [MTRDoorLockClusterDlCredential new];
        params.credential.credentialType =
            [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credential.credentialType)];
        params.credential.credentialIndex = [NSNumber numberWithUnsignedShort:mRequest.credential.credentialIndex];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getCredentialStatusWithParams:params
                                        completion:^(MTRDoorLockClusterGetCredentialStatusResponseParams * _Nullable values,
                                            NSError * _Nullable error) {
                                            NSLog(@"Values: %@", values);
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::GetCredentialStatus::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::DoorLock::Structs::DlCredential::Type> mComplex_Credential;
};

/*
 * Command ClearCredential
 */
class DoorLockClearCredential : public ClusterCommand {
public:
    DoorLockClearCredential()
        : ClusterCommand("clear-credential")
        , mComplex_Credential(&mRequest.credential)
    {
        AddArgument("Credential", &mComplex_Credential);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) command (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRDoorLockClusterClearCredentialParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.credential.IsNull()) {
            params.credential = nil;
        } else {
            params.credential = [MTRDoorLockClusterDlCredential new];
            params.credential.credentialType =
                [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.credential.Value().credentialType)];
            params.credential.credentialIndex = [NSNumber numberWithUnsignedShort:mRequest.credential.Value().credentialIndex];
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearCredentialWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::DoorLock::Commands::ClearCredential::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::DoorLock::Structs::DlCredential::Type>>
        mComplex_Credential;
};

/*
 * Attribute LockState
 */
class ReadDoorLockLockState : public ReadAttribute {
public:
    ReadDoorLockLockState()
        : ReadAttribute("lock-state")
    {
    }

    ~ReadDoorLockLockState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeLockStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LockState response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LockState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockLockState : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLockState()
        : SubscribeAttribute("lock-state")
    {
    }

    ~SubscribeAttributeDoorLockLockState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLockStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LockState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LockType
 */
class ReadDoorLockLockType : public ReadAttribute {
public:
    ReadDoorLockLockType()
        : ReadAttribute("lock-type")
    {
    }

    ~ReadDoorLockLockType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeLockTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LockType response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LockType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockLockType : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLockType()
        : SubscribeAttribute("lock-type")
    {
    }

    ~SubscribeAttributeDoorLockLockType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLockTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LockType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActuatorEnabled
 */
class ReadDoorLockActuatorEnabled : public ReadAttribute {
public:
    ReadDoorLockActuatorEnabled()
        : ReadAttribute("actuator-enabled")
    {
    }

    ~ReadDoorLockActuatorEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeActuatorEnabledWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.ActuatorEnabled response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock ActuatorEnabled read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockActuatorEnabled : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockActuatorEnabled()
        : SubscribeAttribute("actuator-enabled")
    {
    }

    ~SubscribeAttributeDoorLockActuatorEnabled() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActuatorEnabledWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.ActuatorEnabled response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DoorState
 */
class ReadDoorLockDoorState : public ReadAttribute {
public:
    ReadDoorLockDoorState()
        : ReadAttribute("door-state")
    {
    }

    ~ReadDoorLockDoorState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeDoorStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DoorState response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DoorState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockDoorState : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDoorState()
        : SubscribeAttribute("door-state")
    {
    }

    ~SubscribeAttributeDoorLockDoorState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDoorStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DoorState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DoorOpenEvents
 */
class ReadDoorLockDoorOpenEvents : public ReadAttribute {
public:
    ReadDoorLockDoorOpenEvents()
        : ReadAttribute("door-open-events")
    {
    }

    ~ReadDoorLockDoorOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeDoorOpenEventsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DoorOpenEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DoorOpenEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockDoorOpenEvents : public WriteAttribute {
public:
    WriteDoorLockDoorOpenEvents()
        : WriteAttribute("door-open-events")
    {
        AddArgument("attr-name", "door-open-events");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockDoorOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeDoorOpenEventsWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("DoorLock DoorOpenEvents write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeDoorLockDoorOpenEvents : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDoorOpenEvents()
        : SubscribeAttribute("door-open-events")
    {
    }

    ~SubscribeAttributeDoorLockDoorOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDoorOpenEventsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DoorOpenEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DoorClosedEvents
 */
class ReadDoorLockDoorClosedEvents : public ReadAttribute {
public:
    ReadDoorLockDoorClosedEvents()
        : ReadAttribute("door-closed-events")
    {
    }

    ~ReadDoorLockDoorClosedEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeDoorClosedEventsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DoorClosedEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DoorClosedEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockDoorClosedEvents : public WriteAttribute {
public:
    WriteDoorLockDoorClosedEvents()
        : WriteAttribute("door-closed-events")
    {
        AddArgument("attr-name", "door-closed-events");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockDoorClosedEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeDoorClosedEventsWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("DoorLock DoorClosedEvents write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeDoorLockDoorClosedEvents : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDoorClosedEvents()
        : SubscribeAttribute("door-closed-events")
    {
    }

    ~SubscribeAttributeDoorLockDoorClosedEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDoorClosedEventsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DoorClosedEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OpenPeriod
 */
class ReadDoorLockOpenPeriod : public ReadAttribute {
public:
    ReadDoorLockOpenPeriod()
        : ReadAttribute("open-period")
    {
    }

    ~ReadDoorLockOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeOpenPeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.OpenPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock OpenPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockOpenPeriod : public WriteAttribute {
public:
    WriteDoorLockOpenPeriod()
        : WriteAttribute("open-period")
    {
        AddArgument("attr-name", "open-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeOpenPeriodWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("DoorLock OpenPeriod write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeDoorLockOpenPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockOpenPeriod()
        : SubscribeAttribute("open-period")
    {
    }

    ~SubscribeAttributeDoorLockOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOpenPeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.OpenPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfTotalUsersSupported
 */
class ReadDoorLockNumberOfTotalUsersSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfTotalUsersSupported()
        : ReadAttribute("number-of-total-users-supported")
    {
    }

    ~ReadDoorLockNumberOfTotalUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfTotalUsersSupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfTotalUsersSupported response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfTotalUsersSupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfTotalUsersSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfTotalUsersSupported()
        : SubscribeAttribute("number-of-total-users-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfTotalUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfTotalUsersSupportedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfTotalUsersSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfPINUsersSupported
 */
class ReadDoorLockNumberOfPINUsersSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfPINUsersSupported()
        : ReadAttribute("number-of-pinusers-supported")
    {
    }

    ~ReadDoorLockNumberOfPINUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfPINUsersSupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfPINUsersSupported response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfPINUsersSupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfPINUsersSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfPINUsersSupported()
        : SubscribeAttribute("number-of-pinusers-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfPINUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfPINUsersSupportedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfPINUsersSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfRFIDUsersSupported
 */
class ReadDoorLockNumberOfRFIDUsersSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfRFIDUsersSupported()
        : ReadAttribute("number-of-rfidusers-supported")
    {
    }

    ~ReadDoorLockNumberOfRFIDUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfRFIDUsersSupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfRFIDUsersSupported response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfRFIDUsersSupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfRFIDUsersSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfRFIDUsersSupported()
        : SubscribeAttribute("number-of-rfidusers-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfRFIDUsersSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfRFIDUsersSupportedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfRFIDUsersSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfWeekDaySchedulesSupportedPerUser
 */
class ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser : public ReadAttribute {
public:
    ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser()
        : ReadAttribute("number-of-week-day-schedules-supported-per-user")
    {
    }

    ~ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfWeekDaySchedulesSupportedPerUserWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfWeekDaySchedulesSupportedPerUser response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfWeekDaySchedulesSupportedPerUser read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser()
        : SubscribeAttribute("number-of-week-day-schedules-supported-per-user")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfWeekDaySchedulesSupportedPerUserWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfWeekDaySchedulesSupportedPerUser response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfYearDaySchedulesSupportedPerUser
 */
class ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser : public ReadAttribute {
public:
    ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser()
        : ReadAttribute("number-of-year-day-schedules-supported-per-user")
    {
    }

    ~ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfYearDaySchedulesSupportedPerUserWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfYearDaySchedulesSupportedPerUser response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfYearDaySchedulesSupportedPerUser read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser()
        : SubscribeAttribute("number-of-year-day-schedules-supported-per-user")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfYearDaySchedulesSupportedPerUserWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfYearDaySchedulesSupportedPerUser response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfHolidaySchedulesSupported
 */
class ReadDoorLockNumberOfHolidaySchedulesSupported : public ReadAttribute {
public:
    ReadDoorLockNumberOfHolidaySchedulesSupported()
        : ReadAttribute("number-of-holiday-schedules-supported")
    {
    }

    ~ReadDoorLockNumberOfHolidaySchedulesSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster
            readAttributeNumberOfHolidaySchedulesSupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfHolidaySchedulesSupported response %@", [value description]);
                if (error != nil) {
                    LogNSError("DoorLock NumberOfHolidaySchedulesSupported read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported()
        : SubscribeAttribute("number-of-holiday-schedules-supported")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfHolidaySchedulesSupportedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfHolidaySchedulesSupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxPINCodeLength
 */
class ReadDoorLockMaxPINCodeLength : public ReadAttribute {
public:
    ReadDoorLockMaxPINCodeLength()
        : ReadAttribute("max-pincode-length")
    {
    }

    ~ReadDoorLockMaxPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeMaxPINCodeLengthWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MaxPINCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MaxPINCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMaxPINCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMaxPINCodeLength()
        : SubscribeAttribute("max-pincode-length")
    {
    }

    ~SubscribeAttributeDoorLockMaxPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxPINCodeLengthWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MaxPINCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinPINCodeLength
 */
class ReadDoorLockMinPINCodeLength : public ReadAttribute {
public:
    ReadDoorLockMinPINCodeLength()
        : ReadAttribute("min-pincode-length")
    {
    }

    ~ReadDoorLockMinPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeMinPINCodeLengthWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MinPINCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MinPINCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMinPINCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMinPINCodeLength()
        : SubscribeAttribute("min-pincode-length")
    {
    }

    ~SubscribeAttributeDoorLockMinPINCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinPINCodeLengthWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MinPINCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxRFIDCodeLength
 */
class ReadDoorLockMaxRFIDCodeLength : public ReadAttribute {
public:
    ReadDoorLockMaxRFIDCodeLength()
        : ReadAttribute("max-rfidcode-length")
    {
    }

    ~ReadDoorLockMaxRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeMaxRFIDCodeLengthWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MaxRFIDCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MaxRFIDCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMaxRFIDCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMaxRFIDCodeLength()
        : SubscribeAttribute("max-rfidcode-length")
    {
    }

    ~SubscribeAttributeDoorLockMaxRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxRFIDCodeLengthWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MaxRFIDCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinRFIDCodeLength
 */
class ReadDoorLockMinRFIDCodeLength : public ReadAttribute {
public:
    ReadDoorLockMinRFIDCodeLength()
        : ReadAttribute("min-rfidcode-length")
    {
    }

    ~ReadDoorLockMinRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeMinRFIDCodeLengthWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.MinRFIDCodeLength response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock MinRFIDCodeLength read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockMinRFIDCodeLength : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockMinRFIDCodeLength()
        : SubscribeAttribute("min-rfidcode-length")
    {
    }

    ~SubscribeAttributeDoorLockMinRFIDCodeLength() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinRFIDCodeLengthWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.MinRFIDCodeLength response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CredentialRulesSupport
 */
class ReadDoorLockCredentialRulesSupport : public ReadAttribute {
public:
    ReadDoorLockCredentialRulesSupport()
        : ReadAttribute("credential-rules-support")
    {
    }

    ~ReadDoorLockCredentialRulesSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeCredentialRulesSupportWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.CredentialRulesSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock CredentialRulesSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockCredentialRulesSupport : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockCredentialRulesSupport()
        : SubscribeAttribute("credential-rules-support")
    {
    }

    ~SubscribeAttributeDoorLockCredentialRulesSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCredentialRulesSupportWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.CredentialRulesSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfCredentialsSupportedPerUser
 */
class ReadDoorLockNumberOfCredentialsSupportedPerUser : public ReadAttribute {
public:
    ReadDoorLockNumberOfCredentialsSupportedPerUser()
        : ReadAttribute("number-of-credentials-supported-per-user")
    {
    }

    ~ReadDoorLockNumberOfCredentialsSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeNumberOfCredentialsSupportedPerUserWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.NumberOfCredentialsSupportedPerUser response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock NumberOfCredentialsSupportedPerUser read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser()
        : SubscribeAttribute("number-of-credentials-supported-per-user")
    {
    }

    ~SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfCredentialsSupportedPerUserWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.NumberOfCredentialsSupportedPerUser response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Language
 */
class ReadDoorLockLanguage : public ReadAttribute {
public:
    ReadDoorLockLanguage()
        : ReadAttribute("language")
    {
    }

    ~ReadDoorLockLanguage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeLanguageWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.Language response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock Language read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockLanguage : public WriteAttribute {
public:
    WriteDoorLockLanguage()
        : WriteAttribute("language")
    {
        AddArgument("attr-name", "language");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockLanguage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLanguageWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("DoorLock Language write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeDoorLockLanguage : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLanguage()
        : SubscribeAttribute("language")
    {
    }

    ~SubscribeAttributeDoorLockLanguage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLanguageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.Language response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LEDSettings
 */
class ReadDoorLockLEDSettings : public ReadAttribute {
public:
    ReadDoorLockLEDSettings()
        : ReadAttribute("ledsettings")
    {
    }

    ~ReadDoorLockLEDSettings() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeLEDSettingsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LEDSettings response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LEDSettings read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockLEDSettings : public WriteAttribute {
public:
    WriteDoorLockLEDSettings()
        : WriteAttribute("ledsettings")
    {
        AddArgument("attr-name", "ledsettings");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockLEDSettings() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeLEDSettingsWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("DoorLock LEDSettings write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockLEDSettings : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLEDSettings()
        : SubscribeAttribute("ledsettings")
    {
    }

    ~SubscribeAttributeDoorLockLEDSettings() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLEDSettingsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LEDSettings response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AutoRelockTime
 */
class ReadDoorLockAutoRelockTime : public ReadAttribute {
public:
    ReadDoorLockAutoRelockTime()
        : ReadAttribute("auto-relock-time")
    {
    }

    ~ReadDoorLockAutoRelockTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAutoRelockTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.AutoRelockTime response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock AutoRelockTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockAutoRelockTime : public WriteAttribute {
public:
    WriteDoorLockAutoRelockTime()
        : WriteAttribute("auto-relock-time")
    {
        AddArgument("attr-name", "auto-relock-time");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockAutoRelockTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeAutoRelockTimeWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("DoorLock AutoRelockTime write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeDoorLockAutoRelockTime : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockAutoRelockTime()
        : SubscribeAttribute("auto-relock-time")
    {
    }

    ~SubscribeAttributeDoorLockAutoRelockTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAutoRelockTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.AutoRelockTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SoundVolume
 */
class ReadDoorLockSoundVolume : public ReadAttribute {
public:
    ReadDoorLockSoundVolume()
        : ReadAttribute("sound-volume")
    {
    }

    ~ReadDoorLockSoundVolume() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeSoundVolumeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.SoundVolume response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock SoundVolume read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockSoundVolume : public WriteAttribute {
public:
    WriteDoorLockSoundVolume()
        : WriteAttribute("sound-volume")
    {
        AddArgument("attr-name", "sound-volume");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockSoundVolume() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSoundVolumeWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("DoorLock SoundVolume write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockSoundVolume : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockSoundVolume()
        : SubscribeAttribute("sound-volume")
    {
    }

    ~SubscribeAttributeDoorLockSoundVolume() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSoundVolumeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SoundVolume response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperatingMode
 */
class ReadDoorLockOperatingMode : public ReadAttribute {
public:
    ReadDoorLockOperatingMode()
        : ReadAttribute("operating-mode")
    {
    }

    ~ReadDoorLockOperatingMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeOperatingModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.OperatingMode response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock OperatingMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockOperatingMode : public WriteAttribute {
public:
    WriteDoorLockOperatingMode()
        : WriteAttribute("operating-mode")
    {
        AddArgument("attr-name", "operating-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockOperatingMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOperatingModeWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("DoorLock OperatingMode write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockOperatingMode : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockOperatingMode()
        : SubscribeAttribute("operating-mode")
    {
    }

    ~SubscribeAttributeDoorLockOperatingMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOperatingModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.OperatingMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedOperatingModes
 */
class ReadDoorLockSupportedOperatingModes : public ReadAttribute {
public:
    ReadDoorLockSupportedOperatingModes()
        : ReadAttribute("supported-operating-modes")
    {
    }

    ~ReadDoorLockSupportedOperatingModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeSupportedOperatingModesWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.SupportedOperatingModes response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock SupportedOperatingModes read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockSupportedOperatingModes : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockSupportedOperatingModes()
        : SubscribeAttribute("supported-operating-modes")
    {
    }

    ~SubscribeAttributeDoorLockSupportedOperatingModes() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportedOperatingModesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SupportedOperatingModes response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DefaultConfigurationRegister
 */
class ReadDoorLockDefaultConfigurationRegister : public ReadAttribute {
public:
    ReadDoorLockDefaultConfigurationRegister()
        : ReadAttribute("default-configuration-register")
    {
    }

    ~ReadDoorLockDefaultConfigurationRegister() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeDefaultConfigurationRegisterWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.DefaultConfigurationRegister response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock DefaultConfigurationRegister read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockDefaultConfigurationRegister : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockDefaultConfigurationRegister()
        : SubscribeAttribute("default-configuration-register")
    {
    }

    ~SubscribeAttributeDoorLockDefaultConfigurationRegister() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDefaultConfigurationRegisterWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.DefaultConfigurationRegister response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnableLocalProgramming
 */
class ReadDoorLockEnableLocalProgramming : public ReadAttribute {
public:
    ReadDoorLockEnableLocalProgramming()
        : ReadAttribute("enable-local-programming")
    {
    }

    ~ReadDoorLockEnableLocalProgramming() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnableLocalProgrammingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnableLocalProgramming response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnableLocalProgramming read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnableLocalProgramming : public WriteAttribute {
public:
    WriteDoorLockEnableLocalProgramming()
        : WriteAttribute("enable-local-programming")
    {
        AddArgument("attr-name", "enable-local-programming");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnableLocalProgramming() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnableLocalProgrammingWithValue:value
                                                        params:params
                                                    completion:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError("DoorLock EnableLocalProgramming write Error", error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnableLocalProgramming : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnableLocalProgramming()
        : SubscribeAttribute("enable-local-programming")
    {
    }

    ~SubscribeAttributeDoorLockEnableLocalProgramming() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnableLocalProgrammingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnableLocalProgramming response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnableOneTouchLocking
 */
class ReadDoorLockEnableOneTouchLocking : public ReadAttribute {
public:
    ReadDoorLockEnableOneTouchLocking()
        : ReadAttribute("enable-one-touch-locking")
    {
    }

    ~ReadDoorLockEnableOneTouchLocking() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnableOneTouchLockingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnableOneTouchLocking response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnableOneTouchLocking read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnableOneTouchLocking : public WriteAttribute {
public:
    WriteDoorLockEnableOneTouchLocking()
        : WriteAttribute("enable-one-touch-locking")
    {
        AddArgument("attr-name", "enable-one-touch-locking");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnableOneTouchLocking() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnableOneTouchLockingWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("DoorLock EnableOneTouchLocking write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnableOneTouchLocking : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnableOneTouchLocking()
        : SubscribeAttribute("enable-one-touch-locking")
    {
    }

    ~SubscribeAttributeDoorLockEnableOneTouchLocking() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnableOneTouchLockingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnableOneTouchLocking response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnableInsideStatusLED
 */
class ReadDoorLockEnableInsideStatusLED : public ReadAttribute {
public:
    ReadDoorLockEnableInsideStatusLED()
        : ReadAttribute("enable-inside-status-led")
    {
    }

    ~ReadDoorLockEnableInsideStatusLED() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnableInsideStatusLEDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnableInsideStatusLED response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnableInsideStatusLED read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnableInsideStatusLED : public WriteAttribute {
public:
    WriteDoorLockEnableInsideStatusLED()
        : WriteAttribute("enable-inside-status-led")
    {
        AddArgument("attr-name", "enable-inside-status-led");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnableInsideStatusLED() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnableInsideStatusLEDWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("DoorLock EnableInsideStatusLED write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnableInsideStatusLED : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnableInsideStatusLED()
        : SubscribeAttribute("enable-inside-status-led")
    {
    }

    ~SubscribeAttributeDoorLockEnableInsideStatusLED() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnableInsideStatusLEDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnableInsideStatusLED response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnablePrivacyModeButton
 */
class ReadDoorLockEnablePrivacyModeButton : public ReadAttribute {
public:
    ReadDoorLockEnablePrivacyModeButton()
        : ReadAttribute("enable-privacy-mode-button")
    {
    }

    ~ReadDoorLockEnablePrivacyModeButton() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000002B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeEnablePrivacyModeButtonWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.EnablePrivacyModeButton response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock EnablePrivacyModeButton read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockEnablePrivacyModeButton : public WriteAttribute {
public:
    WriteDoorLockEnablePrivacyModeButton()
        : WriteAttribute("enable-privacy-mode-button")
    {
        AddArgument("attr-name", "enable-privacy-mode-button");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockEnablePrivacyModeButton() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeEnablePrivacyModeButtonWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("DoorLock EnablePrivacyModeButton write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockEnablePrivacyModeButton : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockEnablePrivacyModeButton()
        : SubscribeAttribute("enable-privacy-mode-button")
    {
    }

    ~SubscribeAttributeDoorLockEnablePrivacyModeButton() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnablePrivacyModeButtonWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.EnablePrivacyModeButton response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocalProgrammingFeatures
 */
class ReadDoorLockLocalProgrammingFeatures : public ReadAttribute {
public:
    ReadDoorLockLocalProgrammingFeatures()
        : ReadAttribute("local-programming-features")
    {
    }

    ~ReadDoorLockLocalProgrammingFeatures() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000002C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeLocalProgrammingFeaturesWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.LocalProgrammingFeatures response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock LocalProgrammingFeatures read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockLocalProgrammingFeatures : public WriteAttribute {
public:
    WriteDoorLockLocalProgrammingFeatures()
        : WriteAttribute("local-programming-features")
    {
        AddArgument("attr-name", "local-programming-features");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockLocalProgrammingFeatures() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x0000002C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeLocalProgrammingFeaturesWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError("DoorLock LocalProgrammingFeatures write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockLocalProgrammingFeatures : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockLocalProgrammingFeatures()
        : SubscribeAttribute("local-programming-features")
    {
    }

    ~SubscribeAttributeDoorLockLocalProgrammingFeatures() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000002C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLocalProgrammingFeaturesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.LocalProgrammingFeatures response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WrongCodeEntryLimit
 */
class ReadDoorLockWrongCodeEntryLimit : public ReadAttribute {
public:
    ReadDoorLockWrongCodeEntryLimit()
        : ReadAttribute("wrong-code-entry-limit")
    {
    }

    ~ReadDoorLockWrongCodeEntryLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeWrongCodeEntryLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.WrongCodeEntryLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock WrongCodeEntryLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockWrongCodeEntryLimit : public WriteAttribute {
public:
    WriteDoorLockWrongCodeEntryLimit()
        : WriteAttribute("wrong-code-entry-limit")
    {
        AddArgument("attr-name", "wrong-code-entry-limit");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockWrongCodeEntryLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeWrongCodeEntryLimitWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("DoorLock WrongCodeEntryLimit write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockWrongCodeEntryLimit : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockWrongCodeEntryLimit()
        : SubscribeAttribute("wrong-code-entry-limit")
    {
    }

    ~SubscribeAttributeDoorLockWrongCodeEntryLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWrongCodeEntryLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.WrongCodeEntryLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UserCodeTemporaryDisableTime
 */
class ReadDoorLockUserCodeTemporaryDisableTime : public ReadAttribute {
public:
    ReadDoorLockUserCodeTemporaryDisableTime()
        : ReadAttribute("user-code-temporary-disable-time")
    {
    }

    ~ReadDoorLockUserCodeTemporaryDisableTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeUserCodeTemporaryDisableTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.UserCodeTemporaryDisableTime response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock UserCodeTemporaryDisableTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockUserCodeTemporaryDisableTime : public WriteAttribute {
public:
    WriteDoorLockUserCodeTemporaryDisableTime()
        : WriteAttribute("user-code-temporary-disable-time")
    {
        AddArgument("attr-name", "user-code-temporary-disable-time");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockUserCodeTemporaryDisableTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeUserCodeTemporaryDisableTimeWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("DoorLock UserCodeTemporaryDisableTime write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeDoorLockUserCodeTemporaryDisableTime : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockUserCodeTemporaryDisableTime()
        : SubscribeAttribute("user-code-temporary-disable-time")
    {
    }

    ~SubscribeAttributeDoorLockUserCodeTemporaryDisableTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUserCodeTemporaryDisableTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.UserCodeTemporaryDisableTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SendPINOverTheAir
 */
class ReadDoorLockSendPINOverTheAir : public ReadAttribute {
public:
    ReadDoorLockSendPINOverTheAir()
        : ReadAttribute("send-pinover-the-air")
    {
    }

    ~ReadDoorLockSendPINOverTheAir() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeSendPINOverTheAirWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.SendPINOverTheAir response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock SendPINOverTheAir read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockSendPINOverTheAir : public WriteAttribute {
public:
    WriteDoorLockSendPINOverTheAir()
        : WriteAttribute("send-pinover-the-air")
    {
        AddArgument("attr-name", "send-pinover-the-air");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockSendPINOverTheAir() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeSendPINOverTheAirWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("DoorLock SendPINOverTheAir write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockSendPINOverTheAir : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockSendPINOverTheAir()
        : SubscribeAttribute("send-pinover-the-air")
    {
    }

    ~SubscribeAttributeDoorLockSendPINOverTheAir() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSendPINOverTheAirWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.SendPINOverTheAir response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RequirePINforRemoteOperation
 */
class ReadDoorLockRequirePINforRemoteOperation : public ReadAttribute {
public:
    ReadDoorLockRequirePINforRemoteOperation()
        : ReadAttribute("require-pinfor-remote-operation")
    {
    }

    ~ReadDoorLockRequirePINforRemoteOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeRequirePINforRemoteOperationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.RequirePINforRemoteOperation response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock RequirePINforRemoteOperation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockRequirePINforRemoteOperation : public WriteAttribute {
public:
    WriteDoorLockRequirePINforRemoteOperation()
        : WriteAttribute("require-pinfor-remote-operation")
    {
        AddArgument("attr-name", "require-pinfor-remote-operation");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockRequirePINforRemoteOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster
            writeAttributeRequirePINforRemoteOperationWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("DoorLock RequirePINforRemoteOperation write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeDoorLockRequirePINforRemoteOperation : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockRequirePINforRemoteOperation()
        : SubscribeAttribute("require-pinfor-remote-operation")
    {
    }

    ~SubscribeAttributeDoorLockRequirePINforRemoteOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRequirePINforRemoteOperationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.RequirePINforRemoteOperation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ExpiringUserTimeout
 */
class ReadDoorLockExpiringUserTimeout : public ReadAttribute {
public:
    ReadDoorLockExpiringUserTimeout()
        : ReadAttribute("expiring-user-timeout")
    {
    }

    ~ReadDoorLockExpiringUserTimeout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeExpiringUserTimeoutWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.ExpiringUserTimeout response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock ExpiringUserTimeout read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteDoorLockExpiringUserTimeout : public WriteAttribute {
public:
    WriteDoorLockExpiringUserTimeout()
        : WriteAttribute("expiring-user-timeout")
    {
        AddArgument("attr-name", "expiring-user-timeout");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteDoorLockExpiringUserTimeout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) WriteAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeExpiringUserTimeoutWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("DoorLock ExpiringUserTimeout write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeDoorLockExpiringUserTimeout : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockExpiringUserTimeout()
        : SubscribeAttribute("expiring-user-timeout")
    {
    }

    ~SubscribeAttributeDoorLockExpiringUserTimeout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeExpiringUserTimeoutWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.ExpiringUserTimeout response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadDoorLockGeneratedCommandList : public ReadAttribute {
public:
    ReadDoorLockGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadDoorLockGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeDoorLockGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadDoorLockAcceptedCommandList : public ReadAttribute {
public:
    ReadDoorLockAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadDoorLockAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeDoorLockAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadDoorLockAttributeList : public ReadAttribute {
public:
    ReadDoorLockAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadDoorLockAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeDoorLockAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadDoorLockFeatureMap : public ReadAttribute {
public:
    ReadDoorLockFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadDoorLockFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeDoorLockFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadDoorLockClusterRevision : public ReadAttribute {
public:
    ReadDoorLockClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadDoorLockClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"DoorLock.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("DoorLock ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeDoorLockClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeDoorLockClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeDoorLockClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000101) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterDoorLock * cluster = [[MTRBaseClusterDoorLock alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"DoorLock.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WindowCovering                                              | 0x0102 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * UpOrOpen                                                          |   0x00 |
| * DownOrClose                                                       |   0x01 |
| * StopMotion                                                        |   0x02 |
| * GoToLiftValue                                                     |   0x04 |
| * GoToLiftPercentage                                                |   0x05 |
| * GoToTiltValue                                                     |   0x07 |
| * GoToTiltPercentage                                                |   0x08 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Type                                                              | 0x0000 |
| * PhysicalClosedLimitLift                                           | 0x0001 |
| * PhysicalClosedLimitTilt                                           | 0x0002 |
| * CurrentPositionLift                                               | 0x0003 |
| * CurrentPositionTilt                                               | 0x0004 |
| * NumberOfActuationsLift                                            | 0x0005 |
| * NumberOfActuationsTilt                                            | 0x0006 |
| * ConfigStatus                                                      | 0x0007 |
| * CurrentPositionLiftPercentage                                     | 0x0008 |
| * CurrentPositionTiltPercentage                                     | 0x0009 |
| * OperationalStatus                                                 | 0x000A |
| * TargetPositionLiftPercent100ths                                   | 0x000B |
| * TargetPositionTiltPercent100ths                                   | 0x000C |
| * EndProductType                                                    | 0x000D |
| * CurrentPositionLiftPercent100ths                                  | 0x000E |
| * CurrentPositionTiltPercent100ths                                  | 0x000F |
| * InstalledOpenLimitLift                                            | 0x0010 |
| * InstalledClosedLimitLift                                          | 0x0011 |
| * InstalledOpenLimitTilt                                            | 0x0012 |
| * InstalledClosedLimitTilt                                          | 0x0013 |
| * Mode                                                              | 0x0017 |
| * SafetyStatus                                                      | 0x001A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command UpOrOpen
 */
class WindowCoveringUpOrOpen : public ClusterCommand {
public:
    WindowCoveringUpOrOpen()
        : ClusterCommand("up-or-open")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterUpOrOpenParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster upOrOpenWithParams:params
                             completion:^(NSError * _Nullable error) {
                                 responsesNeeded--;
                                 if (error != nil) {
                                     mError = error;
                                     LogNSError("Error", error);
                                 }
                                 if (responsesNeeded == 0) {
                                     SetCommandExitStatus(mError);
                                 }
                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command DownOrClose
 */
class WindowCoveringDownOrClose : public ClusterCommand {
public:
    WindowCoveringDownOrClose()
        : ClusterCommand("down-or-close")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterDownOrCloseParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster downOrCloseWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command StopMotion
 */
class WindowCoveringStopMotion : public ClusterCommand {
public:
    WindowCoveringStopMotion()
        : ClusterCommand("stop-motion")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterStopMotionParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopMotionWithParams:params
                               completion:^(NSError * _Nullable error) {
                                   responsesNeeded--;
                                   if (error != nil) {
                                       mError = error;
                                       LogNSError("Error", error);
                                   }
                                   if (responsesNeeded == 0) {
                                       SetCommandExitStatus(mError);
                                   }
                               }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command GoToLiftValue
 */
class WindowCoveringGoToLiftValue : public ClusterCommand {
public:
    WindowCoveringGoToLiftValue()
        : ClusterCommand("go-to-lift-value")
    {
        AddArgument("LiftValue", 0, UINT16_MAX, &mRequest.liftValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterGoToLiftValueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.liftValue = [NSNumber numberWithUnsignedShort:mRequest.liftValue];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster goToLiftValueWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToLiftValue::Type mRequest;
};

/*
 * Command GoToLiftPercentage
 */
class WindowCoveringGoToLiftPercentage : public ClusterCommand {
public:
    WindowCoveringGoToLiftPercentage()
        : ClusterCommand("go-to-lift-percentage")
    {
        AddArgument("LiftPercent100thsValue", 0, UINT16_MAX, &mRequest.liftPercent100thsValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterGoToLiftPercentageParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.liftPercent100thsValue = [NSNumber numberWithUnsignedShort:mRequest.liftPercent100thsValue];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster goToLiftPercentageWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToLiftPercentage::Type mRequest;
};

/*
 * Command GoToTiltValue
 */
class WindowCoveringGoToTiltValue : public ClusterCommand {
public:
    WindowCoveringGoToTiltValue()
        : ClusterCommand("go-to-tilt-value")
    {
        AddArgument("TiltValue", 0, UINT16_MAX, &mRequest.tiltValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterGoToTiltValueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.tiltValue = [NSNumber numberWithUnsignedShort:mRequest.tiltValue];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster goToTiltValueWithParams:params
                                  completion:^(NSError * _Nullable error) {
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToTiltValue::Type mRequest;
};

/*
 * Command GoToTiltPercentage
 */
class WindowCoveringGoToTiltPercentage : public ClusterCommand {
public:
    WindowCoveringGoToTiltPercentage()
        : ClusterCommand("go-to-tilt-percentage")
    {
        AddArgument("TiltPercent100thsValue", 0, UINT16_MAX, &mRequest.tiltPercent100thsValue);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRWindowCoveringClusterGoToTiltPercentageParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.tiltPercent100thsValue = [NSNumber numberWithUnsignedShort:mRequest.tiltPercent100thsValue];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster goToTiltPercentageWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::WindowCovering::Commands::GoToTiltPercentage::Type mRequest;
};

/*
 * Attribute Type
 */
class ReadWindowCoveringType : public ReadAttribute {
public:
    ReadWindowCoveringType()
        : ReadAttribute("type")
    {
    }

    ~ReadWindowCoveringType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.Type response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering Type read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringType : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringType()
        : SubscribeAttribute("type")
    {
    }

    ~SubscribeAttributeWindowCoveringType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.Type response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalClosedLimitLift
 */
class ReadWindowCoveringPhysicalClosedLimitLift : public ReadAttribute {
public:
    ReadWindowCoveringPhysicalClosedLimitLift()
        : ReadAttribute("physical-closed-limit-lift")
    {
    }

    ~ReadWindowCoveringPhysicalClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributePhysicalClosedLimitLiftWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.PhysicalClosedLimitLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering PhysicalClosedLimitLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringPhysicalClosedLimitLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringPhysicalClosedLimitLift()
        : SubscribeAttribute("physical-closed-limit-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringPhysicalClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalClosedLimitLiftWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.PhysicalClosedLimitLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalClosedLimitTilt
 */
class ReadWindowCoveringPhysicalClosedLimitTilt : public ReadAttribute {
public:
    ReadWindowCoveringPhysicalClosedLimitTilt()
        : ReadAttribute("physical-closed-limit-tilt")
    {
    }

    ~ReadWindowCoveringPhysicalClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributePhysicalClosedLimitTiltWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.PhysicalClosedLimitTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering PhysicalClosedLimitTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt()
        : SubscribeAttribute("physical-closed-limit-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalClosedLimitTiltWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.PhysicalClosedLimitTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionLift
 */
class ReadWindowCoveringCurrentPositionLift : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionLift()
        : ReadAttribute("current-position-lift")
    {
    }

    ~ReadWindowCoveringCurrentPositionLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionLiftWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionLift()
        : SubscribeAttribute("current-position-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionLiftWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionTilt
 */
class ReadWindowCoveringCurrentPositionTilt : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionTilt()
        : ReadAttribute("current-position-tilt")
    {
    }

    ~ReadWindowCoveringCurrentPositionTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionTiltWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionTilt()
        : SubscribeAttribute("current-position-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionTiltWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfActuationsLift
 */
class ReadWindowCoveringNumberOfActuationsLift : public ReadAttribute {
public:
    ReadWindowCoveringNumberOfActuationsLift()
        : ReadAttribute("number-of-actuations-lift")
    {
    }

    ~ReadWindowCoveringNumberOfActuationsLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeNumberOfActuationsLiftWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.NumberOfActuationsLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering NumberOfActuationsLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringNumberOfActuationsLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringNumberOfActuationsLift()
        : SubscribeAttribute("number-of-actuations-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringNumberOfActuationsLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfActuationsLiftWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.NumberOfActuationsLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfActuationsTilt
 */
class ReadWindowCoveringNumberOfActuationsTilt : public ReadAttribute {
public:
    ReadWindowCoveringNumberOfActuationsTilt()
        : ReadAttribute("number-of-actuations-tilt")
    {
    }

    ~ReadWindowCoveringNumberOfActuationsTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeNumberOfActuationsTiltWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.NumberOfActuationsTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering NumberOfActuationsTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringNumberOfActuationsTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringNumberOfActuationsTilt()
        : SubscribeAttribute("number-of-actuations-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringNumberOfActuationsTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfActuationsTiltWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.NumberOfActuationsTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ConfigStatus
 */
class ReadWindowCoveringConfigStatus : public ReadAttribute {
public:
    ReadWindowCoveringConfigStatus()
        : ReadAttribute("config-status")
    {
    }

    ~ReadWindowCoveringConfigStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeConfigStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.ConfigStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering ConfigStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringConfigStatus : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringConfigStatus()
        : SubscribeAttribute("config-status")
    {
    }

    ~SubscribeAttributeWindowCoveringConfigStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeConfigStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.ConfigStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionLiftPercentage
 */
class ReadWindowCoveringCurrentPositionLiftPercentage : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionLiftPercentage()
        : ReadAttribute("current-position-lift-percentage")
    {
    }

    ~ReadWindowCoveringCurrentPositionLiftPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionLiftPercentageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionLiftPercentage response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionLiftPercentage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage()
        : SubscribeAttribute("current-position-lift-percentage")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionLiftPercentageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLiftPercentage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionTiltPercentage
 */
class ReadWindowCoveringCurrentPositionTiltPercentage : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionTiltPercentage()
        : ReadAttribute("current-position-tilt-percentage")
    {
    }

    ~ReadWindowCoveringCurrentPositionTiltPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeCurrentPositionTiltPercentageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.CurrentPositionTiltPercentage response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering CurrentPositionTiltPercentage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage()
        : SubscribeAttribute("current-position-tilt-percentage")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionTiltPercentageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTiltPercentage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperationalStatus
 */
class ReadWindowCoveringOperationalStatus : public ReadAttribute {
public:
    ReadWindowCoveringOperationalStatus()
        : ReadAttribute("operational-status")
    {
    }

    ~ReadWindowCoveringOperationalStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeOperationalStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.OperationalStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering OperationalStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringOperationalStatus : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringOperationalStatus()
        : SubscribeAttribute("operational-status")
    {
    }

    ~SubscribeAttributeWindowCoveringOperationalStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOperationalStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.OperationalStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TargetPositionLiftPercent100ths
 */
class ReadWindowCoveringTargetPositionLiftPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringTargetPositionLiftPercent100ths()
        : ReadAttribute("target-position-lift-percent100ths")
    {
    }

    ~ReadWindowCoveringTargetPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeTargetPositionLiftPercent100thsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.TargetPositionLiftPercent100ths response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering TargetPositionLiftPercent100ths read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths()
        : SubscribeAttribute("target-position-lift-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTargetPositionLiftPercent100thsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.TargetPositionLiftPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TargetPositionTiltPercent100ths
 */
class ReadWindowCoveringTargetPositionTiltPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringTargetPositionTiltPercent100ths()
        : ReadAttribute("target-position-tilt-percent100ths")
    {
    }

    ~ReadWindowCoveringTargetPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeTargetPositionTiltPercent100thsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.TargetPositionTiltPercent100ths response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering TargetPositionTiltPercent100ths read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths()
        : SubscribeAttribute("target-position-tilt-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTargetPositionTiltPercent100thsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.TargetPositionTiltPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EndProductType
 */
class ReadWindowCoveringEndProductType : public ReadAttribute {
public:
    ReadWindowCoveringEndProductType()
        : ReadAttribute("end-product-type")
    {
    }

    ~ReadWindowCoveringEndProductType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeEndProductTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.EndProductType response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering EndProductType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringEndProductType : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringEndProductType()
        : SubscribeAttribute("end-product-type")
    {
    }

    ~SubscribeAttributeWindowCoveringEndProductType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEndProductTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.EndProductType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionLiftPercent100ths
 */
class ReadWindowCoveringCurrentPositionLiftPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionLiftPercent100ths()
        : ReadAttribute("current-position-lift-percent100ths")
    {
    }

    ~ReadWindowCoveringCurrentPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeCurrentPositionLiftPercent100thsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLiftPercent100ths response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering CurrentPositionLiftPercent100ths read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths()
        : SubscribeAttribute("current-position-lift-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionLiftPercent100thsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionLiftPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentPositionTiltPercent100ths
 */
class ReadWindowCoveringCurrentPositionTiltPercent100ths : public ReadAttribute {
public:
    ReadWindowCoveringCurrentPositionTiltPercent100ths()
        : ReadAttribute("current-position-tilt-percent100ths")
    {
    }

    ~ReadWindowCoveringCurrentPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster
            readAttributeCurrentPositionTiltPercent100thsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTiltPercent100ths response %@", [value description]);
                if (error != nil) {
                    LogNSError("WindowCovering CurrentPositionTiltPercent100ths read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths()
        : SubscribeAttribute("current-position-tilt-percent100ths")
    {
    }

    ~SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentPositionTiltPercent100thsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.CurrentPositionTiltPercent100ths response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledOpenLimitLift
 */
class ReadWindowCoveringInstalledOpenLimitLift : public ReadAttribute {
public:
    ReadWindowCoveringInstalledOpenLimitLift()
        : ReadAttribute("installed-open-limit-lift")
    {
    }

    ~ReadWindowCoveringInstalledOpenLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeInstalledOpenLimitLiftWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.InstalledOpenLimitLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering InstalledOpenLimitLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledOpenLimitLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledOpenLimitLift()
        : SubscribeAttribute("installed-open-limit-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledOpenLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstalledOpenLimitLiftWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledOpenLimitLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledClosedLimitLift
 */
class ReadWindowCoveringInstalledClosedLimitLift : public ReadAttribute {
public:
    ReadWindowCoveringInstalledClosedLimitLift()
        : ReadAttribute("installed-closed-limit-lift")
    {
    }

    ~ReadWindowCoveringInstalledClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeInstalledClosedLimitLiftWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.InstalledClosedLimitLift response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering InstalledClosedLimitLift read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledClosedLimitLift : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledClosedLimitLift()
        : SubscribeAttribute("installed-closed-limit-lift")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledClosedLimitLift() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstalledClosedLimitLiftWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledClosedLimitLift response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledOpenLimitTilt
 */
class ReadWindowCoveringInstalledOpenLimitTilt : public ReadAttribute {
public:
    ReadWindowCoveringInstalledOpenLimitTilt()
        : ReadAttribute("installed-open-limit-tilt")
    {
    }

    ~ReadWindowCoveringInstalledOpenLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeInstalledOpenLimitTiltWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.InstalledOpenLimitTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering InstalledOpenLimitTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledOpenLimitTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledOpenLimitTilt()
        : SubscribeAttribute("installed-open-limit-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledOpenLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstalledOpenLimitTiltWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledOpenLimitTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstalledClosedLimitTilt
 */
class ReadWindowCoveringInstalledClosedLimitTilt : public ReadAttribute {
public:
    ReadWindowCoveringInstalledClosedLimitTilt()
        : ReadAttribute("installed-closed-limit-tilt")
    {
    }

    ~ReadWindowCoveringInstalledClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeInstalledClosedLimitTiltWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.InstalledClosedLimitTilt response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering InstalledClosedLimitTilt read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringInstalledClosedLimitTilt : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringInstalledClosedLimitTilt()
        : SubscribeAttribute("installed-closed-limit-tilt")
    {
    }

    ~SubscribeAttributeWindowCoveringInstalledClosedLimitTilt() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstalledClosedLimitTiltWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.InstalledClosedLimitTilt response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Mode
 */
class ReadWindowCoveringMode : public ReadAttribute {
public:
    ReadWindowCoveringMode()
        : ReadAttribute("mode")
    {
    }

    ~ReadWindowCoveringMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.Mode response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering Mode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteWindowCoveringMode : public WriteAttribute {
public:
    WriteWindowCoveringMode()
        : WriteAttribute("mode")
    {
        AddArgument("attr-name", "mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteWindowCoveringMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeModeWithValue:value
                                      params:params
                                  completion:^(NSError * _Nullable error) {
                                      if (error != nil) {
                                          LogNSError("WindowCovering Mode write Error", error);
                                      }
                                      SetCommandExitStatus(error);
                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeWindowCoveringMode : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringMode()
        : SubscribeAttribute("mode")
    {
    }

    ~SubscribeAttributeWindowCoveringMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.Mode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SafetyStatus
 */
class ReadWindowCoveringSafetyStatus : public ReadAttribute {
public:
    ReadWindowCoveringSafetyStatus()
        : ReadAttribute("safety-status")
    {
    }

    ~ReadWindowCoveringSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeSafetyStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.SafetyStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering SafetyStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringSafetyStatus : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringSafetyStatus()
        : SubscribeAttribute("safety-status")
    {
    }

    ~SubscribeAttributeWindowCoveringSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSafetyStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.SafetyStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadWindowCoveringGeneratedCommandList : public ReadAttribute {
public:
    ReadWindowCoveringGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadWindowCoveringGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeWindowCoveringGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadWindowCoveringAcceptedCommandList : public ReadAttribute {
public:
    ReadWindowCoveringAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadWindowCoveringAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeWindowCoveringAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadWindowCoveringAttributeList : public ReadAttribute {
public:
    ReadWindowCoveringAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadWindowCoveringAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeWindowCoveringAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadWindowCoveringFeatureMap : public ReadAttribute {
public:
    ReadWindowCoveringFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadWindowCoveringFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeWindowCoveringFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadWindowCoveringClusterRevision : public ReadAttribute {
public:
    ReadWindowCoveringClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadWindowCoveringClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WindowCovering.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("WindowCovering ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWindowCoveringClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeWindowCoveringClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeWindowCoveringClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000102) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWindowCovering * cluster = [[MTRBaseClusterWindowCovering alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WindowCovering.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BarrierControl                                              | 0x0103 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * BarrierControlGoToPercent                                         |   0x00 |
| * BarrierControlStop                                                |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * BarrierMovingState                                                | 0x0001 |
| * BarrierSafetyStatus                                               | 0x0002 |
| * BarrierCapabilities                                               | 0x0003 |
| * BarrierOpenEvents                                                 | 0x0004 |
| * BarrierCloseEvents                                                | 0x0005 |
| * BarrierCommandOpenEvents                                          | 0x0006 |
| * BarrierCommandCloseEvents                                         | 0x0007 |
| * BarrierOpenPeriod                                                 | 0x0008 |
| * BarrierClosePeriod                                                | 0x0009 |
| * BarrierPosition                                                   | 0x000A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command BarrierControlGoToPercent
 */
class BarrierControlBarrierControlGoToPercent : public ClusterCommand {
public:
    BarrierControlBarrierControlGoToPercent()
        : ClusterCommand("barrier-control-go-to-percent")
    {
        AddArgument("PercentOpen", 0, UINT8_MAX, &mRequest.percentOpen);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBarrierControlClusterBarrierControlGoToPercentParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.percentOpen = [NSNumber numberWithUnsignedChar:mRequest.percentOpen];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster barrierControlGoToPercentWithParams:params
                                              completion:^(NSError * _Nullable error) {
                                                  responsesNeeded--;
                                                  if (error != nil) {
                                                      mError = error;
                                                      LogNSError("Error", error);
                                                  }
                                                  if (responsesNeeded == 0) {
                                                      SetCommandExitStatus(mError);
                                                  }
                                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::BarrierControl::Commands::BarrierControlGoToPercent::Type mRequest;
};

/*
 * Command BarrierControlStop
 */
class BarrierControlBarrierControlStop : public ClusterCommand {
public:
    BarrierControlBarrierControlStop()
        : ClusterCommand("barrier-control-stop")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        __auto_type * params = [[MTRBarrierControlClusterBarrierControlStopParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster barrierControlStopWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute BarrierMovingState
 */
class ReadBarrierControlBarrierMovingState : public ReadAttribute {
public:
    ReadBarrierControlBarrierMovingState()
        : ReadAttribute("barrier-moving-state")
    {
    }

    ~ReadBarrierControlBarrierMovingState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierMovingStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierMovingState response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierMovingState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierMovingState : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierMovingState()
        : SubscribeAttribute("barrier-moving-state")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierMovingState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierMovingStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierMovingState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierSafetyStatus
 */
class ReadBarrierControlBarrierSafetyStatus : public ReadAttribute {
public:
    ReadBarrierControlBarrierSafetyStatus()
        : ReadAttribute("barrier-safety-status")
    {
    }

    ~ReadBarrierControlBarrierSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierSafetyStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierSafetyStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierSafetyStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierSafetyStatus : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierSafetyStatus()
        : SubscribeAttribute("barrier-safety-status")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierSafetyStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierSafetyStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierSafetyStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCapabilities
 */
class ReadBarrierControlBarrierCapabilities : public ReadAttribute {
public:
    ReadBarrierControlBarrierCapabilities()
        : ReadAttribute("barrier-capabilities")
    {
    }

    ~ReadBarrierControlBarrierCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierCapabilitiesWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierCapabilities response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierCapabilities read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierCapabilities : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCapabilities()
        : SubscribeAttribute("barrier-capabilities")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierCapabilitiesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCapabilities response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierOpenEvents
 */
class ReadBarrierControlBarrierOpenEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierOpenEvents()
        : ReadAttribute("barrier-open-events")
    {
    }

    ~ReadBarrierControlBarrierOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierOpenEventsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierOpenEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierOpenEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierOpenEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierOpenEvents()
        : WriteAttribute("barrier-open-events")
    {
        AddArgument("attr-name", "barrier-open-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierOpenEventsWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("BarrierControl BarrierOpenEvents write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierOpenEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierOpenEvents()
        : SubscribeAttribute("barrier-open-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierOpenEventsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierOpenEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCloseEvents
 */
class ReadBarrierControlBarrierCloseEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierCloseEvents()
        : ReadAttribute("barrier-close-events")
    {
    }

    ~ReadBarrierControlBarrierCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierCloseEventsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierCloseEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierCloseEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierCloseEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierCloseEvents()
        : WriteAttribute("barrier-close-events")
    {
        AddArgument("attr-name", "barrier-close-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierCloseEventsWithValue:value
                                                    params:params
                                                completion:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("BarrierControl BarrierCloseEvents write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierCloseEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCloseEvents()
        : SubscribeAttribute("barrier-close-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierCloseEventsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCloseEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCommandOpenEvents
 */
class ReadBarrierControlBarrierCommandOpenEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierCommandOpenEvents()
        : ReadAttribute("barrier-command-open-events")
    {
    }

    ~ReadBarrierControlBarrierCommandOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierCommandOpenEventsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierCommandOpenEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierCommandOpenEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierCommandOpenEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierCommandOpenEvents()
        : WriteAttribute("barrier-command-open-events")
    {
        AddArgument("attr-name", "barrier-command-open-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierCommandOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeBarrierCommandOpenEventsWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("BarrierControl BarrierCommandOpenEvents write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierCommandOpenEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCommandOpenEvents()
        : SubscribeAttribute("barrier-command-open-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCommandOpenEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierCommandOpenEventsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCommandOpenEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierCommandCloseEvents
 */
class ReadBarrierControlBarrierCommandCloseEvents : public ReadAttribute {
public:
    ReadBarrierControlBarrierCommandCloseEvents()
        : ReadAttribute("barrier-command-close-events")
    {
    }

    ~ReadBarrierControlBarrierCommandCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierCommandCloseEventsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierCommandCloseEvents response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierCommandCloseEvents read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierCommandCloseEvents : public WriteAttribute {
public:
    WriteBarrierControlBarrierCommandCloseEvents()
        : WriteAttribute("barrier-command-close-events")
    {
        AddArgument("attr-name", "barrier-command-close-events");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierCommandCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeBarrierCommandCloseEventsWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("BarrierControl BarrierCommandCloseEvents write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierCommandCloseEvents : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierCommandCloseEvents()
        : SubscribeAttribute("barrier-command-close-events")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierCommandCloseEvents() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierCommandCloseEventsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierCommandCloseEvents response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierOpenPeriod
 */
class ReadBarrierControlBarrierOpenPeriod : public ReadAttribute {
public:
    ReadBarrierControlBarrierOpenPeriod()
        : ReadAttribute("barrier-open-period")
    {
    }

    ~ReadBarrierControlBarrierOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierOpenPeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierOpenPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierOpenPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierOpenPeriod : public WriteAttribute {
public:
    WriteBarrierControlBarrierOpenPeriod()
        : WriteAttribute("barrier-open-period")
    {
        AddArgument("attr-name", "barrier-open-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierOpenPeriodWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("BarrierControl BarrierOpenPeriod write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierOpenPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierOpenPeriod()
        : SubscribeAttribute("barrier-open-period")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierOpenPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierOpenPeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierOpenPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierClosePeriod
 */
class ReadBarrierControlBarrierClosePeriod : public ReadAttribute {
public:
    ReadBarrierControlBarrierClosePeriod()
        : ReadAttribute("barrier-close-period")
    {
    }

    ~ReadBarrierControlBarrierClosePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierClosePeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierClosePeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierClosePeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBarrierControlBarrierClosePeriod : public WriteAttribute {
public:
    WriteBarrierControlBarrierClosePeriod()
        : WriteAttribute("barrier-close-period")
    {
        AddArgument("attr-name", "barrier-close-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBarrierControlBarrierClosePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) WriteAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBarrierClosePeriodWithValue:value
                                                    params:params
                                                completion:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("BarrierControl BarrierClosePeriod write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeBarrierControlBarrierClosePeriod : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierClosePeriod()
        : SubscribeAttribute("barrier-close-period")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierClosePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierClosePeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierClosePeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BarrierPosition
 */
class ReadBarrierControlBarrierPosition : public ReadAttribute {
public:
    ReadBarrierControlBarrierPosition()
        : ReadAttribute("barrier-position")
    {
    }

    ~ReadBarrierControlBarrierPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeBarrierPositionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.BarrierPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl BarrierPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlBarrierPosition : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlBarrierPosition()
        : SubscribeAttribute("barrier-position")
    {
    }

    ~SubscribeAttributeBarrierControlBarrierPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBarrierPositionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.BarrierPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBarrierControlGeneratedCommandList : public ReadAttribute {
public:
    ReadBarrierControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBarrierControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBarrierControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBarrierControlAcceptedCommandList : public ReadAttribute {
public:
    ReadBarrierControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBarrierControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBarrierControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBarrierControlAttributeList : public ReadAttribute {
public:
    ReadBarrierControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBarrierControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBarrierControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBarrierControlFeatureMap : public ReadAttribute {
public:
    ReadBarrierControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBarrierControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBarrierControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBarrierControlClusterRevision : public ReadAttribute {
public:
    ReadBarrierControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBarrierControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BarrierControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BarrierControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBarrierControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBarrierControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBarrierControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000103) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBarrierControl * cluster = [[MTRBaseClusterBarrierControl alloc] initWithDevice:device
                                                                                           endpointID:@(endpointId)
                                                                                                queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BarrierControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PumpConfigurationAndControl                                 | 0x0200 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MaxPressure                                                       | 0x0000 |
| * MaxSpeed                                                          | 0x0001 |
| * MaxFlow                                                           | 0x0002 |
| * MinConstPressure                                                  | 0x0003 |
| * MaxConstPressure                                                  | 0x0004 |
| * MinCompPressure                                                   | 0x0005 |
| * MaxCompPressure                                                   | 0x0006 |
| * MinConstSpeed                                                     | 0x0007 |
| * MaxConstSpeed                                                     | 0x0008 |
| * MinConstFlow                                                      | 0x0009 |
| * MaxConstFlow                                                      | 0x000A |
| * MinConstTemp                                                      | 0x000B |
| * MaxConstTemp                                                      | 0x000C |
| * PumpStatus                                                        | 0x0010 |
| * EffectiveOperationMode                                            | 0x0011 |
| * EffectiveControlMode                                              | 0x0012 |
| * Capacity                                                          | 0x0013 |
| * Speed                                                             | 0x0014 |
| * LifetimeRunningHours                                              | 0x0015 |
| * Power                                                             | 0x0016 |
| * LifetimeEnergyConsumed                                            | 0x0017 |
| * OperationMode                                                     | 0x0020 |
| * ControlMode                                                       | 0x0021 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * SupplyVoltageLow                                                  | 0x0000 |
| * SupplyVoltageHigh                                                 | 0x0001 |
| * PowerMissingPhase                                                 | 0x0002 |
| * SystemPressureLow                                                 | 0x0003 |
| * SystemPressureHigh                                                | 0x0004 |
| * DryRunning                                                        | 0x0005 |
| * MotorTemperatureHigh                                              | 0x0006 |
| * PumpMotorFatalFailure                                             | 0x0007 |
| * ElectronicTemperatureHigh                                         | 0x0008 |
| * PumpBlocked                                                       | 0x0009 |
| * SensorFailure                                                     | 0x000A |
| * ElectronicNonFatalFailure                                         | 0x000B |
| * ElectronicFatalFailure                                            | 0x000C |
| * GeneralFault                                                      | 0x000D |
| * Leakage                                                           | 0x000E |
| * AirDetection                                                      | 0x000F |
| * TurbineOperation                                                  | 0x0010 |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MaxPressure
 */
class ReadPumpConfigurationAndControlMaxPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxPressure()
        : ReadAttribute("max-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMaxPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxPressureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxPressure()
        : SubscribeAttribute("max-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxPressureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxSpeed
 */
class ReadPumpConfigurationAndControlMaxSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxSpeed()
        : ReadAttribute("max-speed")
    {
    }

    ~ReadPumpConfigurationAndControlMaxSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxSpeedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxSpeed()
        : SubscribeAttribute("max-speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxSpeedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxFlow
 */
class ReadPumpConfigurationAndControlMaxFlow : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxFlow()
        : ReadAttribute("max-flow")
    {
    }

    ~ReadPumpConfigurationAndControlMaxFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxFlowWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxFlow response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxFlow read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxFlow : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxFlow()
        : SubscribeAttribute("max-flow")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxFlowWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxFlow response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstPressure
 */
class ReadPumpConfigurationAndControlMinConstPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstPressure()
        : ReadAttribute("min-const-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinConstPressureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstPressure()
        : SubscribeAttribute("min-const-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinConstPressureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstPressure
 */
class ReadPumpConfigurationAndControlMaxConstPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstPressure()
        : ReadAttribute("max-const-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxConstPressureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstPressure()
        : SubscribeAttribute("max-const-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxConstPressureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinCompPressure
 */
class ReadPumpConfigurationAndControlMinCompPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinCompPressure()
        : ReadAttribute("min-comp-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMinCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinCompPressureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinCompPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinCompPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinCompPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinCompPressure()
        : SubscribeAttribute("min-comp-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinCompPressureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinCompPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxCompPressure
 */
class ReadPumpConfigurationAndControlMaxCompPressure : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxCompPressure()
        : ReadAttribute("max-comp-pressure")
    {
    }

    ~ReadPumpConfigurationAndControlMaxCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxCompPressureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxCompPressure response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxCompPressure read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxCompPressure : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxCompPressure()
        : SubscribeAttribute("max-comp-pressure")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxCompPressure() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxCompPressureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxCompPressure response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstSpeed
 */
class ReadPumpConfigurationAndControlMinConstSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstSpeed()
        : ReadAttribute("min-const-speed")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinConstSpeedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstSpeed()
        : SubscribeAttribute("min-const-speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinConstSpeedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstSpeed
 */
class ReadPumpConfigurationAndControlMaxConstSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstSpeed()
        : ReadAttribute("max-const-speed")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxConstSpeedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstSpeed()
        : SubscribeAttribute("max-const-speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxConstSpeedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstFlow
 */
class ReadPumpConfigurationAndControlMinConstFlow : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstFlow()
        : ReadAttribute("min-const-flow")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinConstFlowWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstFlow response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstFlow read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstFlow : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstFlow()
        : SubscribeAttribute("min-const-flow")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinConstFlowWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstFlow response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstFlow
 */
class ReadPumpConfigurationAndControlMaxConstFlow : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstFlow()
        : ReadAttribute("max-const-flow")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxConstFlowWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstFlow response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstFlow read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstFlow : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstFlow()
        : SubscribeAttribute("max-const-flow")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstFlow() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxConstFlowWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstFlow response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinConstTemp
 */
class ReadPumpConfigurationAndControlMinConstTemp : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMinConstTemp()
        : ReadAttribute("min-const-temp")
    {
    }

    ~ReadPumpConfigurationAndControlMinConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinConstTempWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MinConstTemp response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MinConstTemp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMinConstTemp : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMinConstTemp()
        : SubscribeAttribute("min-const-temp")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMinConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinConstTempWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MinConstTemp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxConstTemp
 */
class ReadPumpConfigurationAndControlMaxConstTemp : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlMaxConstTemp()
        : ReadAttribute("max-const-temp")
    {
    }

    ~ReadPumpConfigurationAndControlMaxConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxConstTempWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.MaxConstTemp response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl MaxConstTemp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlMaxConstTemp : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlMaxConstTemp()
        : SubscribeAttribute("max-const-temp")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlMaxConstTemp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxConstTempWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.MaxConstTemp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PumpStatus
 */
class ReadPumpConfigurationAndControlPumpStatus : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlPumpStatus()
        : ReadAttribute("pump-status")
    {
    }

    ~ReadPumpConfigurationAndControlPumpStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePumpStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.PumpStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl PumpStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlPumpStatus : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlPumpStatus()
        : SubscribeAttribute("pump-status")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlPumpStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePumpStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.PumpStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EffectiveOperationMode
 */
class ReadPumpConfigurationAndControlEffectiveOperationMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlEffectiveOperationMode()
        : ReadAttribute("effective-operation-mode")
    {
    }

    ~ReadPumpConfigurationAndControlEffectiveOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeEffectiveOperationModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.EffectiveOperationMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl EffectiveOperationMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode()
        : SubscribeAttribute("effective-operation-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEffectiveOperationModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.EffectiveOperationMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EffectiveControlMode
 */
class ReadPumpConfigurationAndControlEffectiveControlMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlEffectiveControlMode()
        : ReadAttribute("effective-control-mode")
    {
    }

    ~ReadPumpConfigurationAndControlEffectiveControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeEffectiveControlModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.EffectiveControlMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl EffectiveControlMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlEffectiveControlMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlEffectiveControlMode()
        : SubscribeAttribute("effective-control-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlEffectiveControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEffectiveControlModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.EffectiveControlMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Capacity
 */
class ReadPumpConfigurationAndControlCapacity : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlCapacity()
        : ReadAttribute("capacity")
    {
    }

    ~ReadPumpConfigurationAndControlCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeCapacityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.Capacity response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl Capacity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlCapacity : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlCapacity()
        : SubscribeAttribute("capacity")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCapacityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.Capacity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Speed
 */
class ReadPumpConfigurationAndControlSpeed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlSpeed()
        : ReadAttribute("speed")
    {
    }

    ~ReadPumpConfigurationAndControlSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeSpeedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.Speed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl Speed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlSpeed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlSpeed()
        : SubscribeAttribute("speed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSpeedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.Speed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LifetimeRunningHours
 */
class ReadPumpConfigurationAndControlLifetimeRunningHours : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlLifetimeRunningHours()
        : ReadAttribute("lifetime-running-hours")
    {
    }

    ~ReadPumpConfigurationAndControlLifetimeRunningHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeLifetimeRunningHoursWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.LifetimeRunningHours response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl LifetimeRunningHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlLifetimeRunningHours : public WriteAttribute {
public:
    WritePumpConfigurationAndControlLifetimeRunningHours()
        : WriteAttribute("lifetime-running-hours")
    {
        AddArgument("attr-name", "lifetime-running-hours");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlLifetimeRunningHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeLifetimeRunningHoursWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("PumpConfigurationAndControl LifetimeRunningHours write Error",
                                                              error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours()
        : SubscribeAttribute("lifetime-running-hours")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLifetimeRunningHoursWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.LifetimeRunningHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Power
 */
class ReadPumpConfigurationAndControlPower : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlPower()
        : ReadAttribute("power")
    {
    }

    ~ReadPumpConfigurationAndControlPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributePowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.Power response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl Power read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlPower : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlPower()
        : SubscribeAttribute("power")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.Power response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LifetimeEnergyConsumed
 */
class ReadPumpConfigurationAndControlLifetimeEnergyConsumed : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlLifetimeEnergyConsumed()
        : ReadAttribute("lifetime-energy-consumed")
    {
    }

    ~ReadPumpConfigurationAndControlLifetimeEnergyConsumed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeLifetimeEnergyConsumedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.LifetimeEnergyConsumed response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl LifetimeEnergyConsumed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlLifetimeEnergyConsumed : public WriteAttribute {
public:
    WritePumpConfigurationAndControlLifetimeEnergyConsumed()
        : WriteAttribute("lifetime-energy-consumed")
    {
        AddArgument("attr-name", "lifetime-energy-consumed");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlLifetimeEnergyConsumed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster
            writeAttributeLifetimeEnergyConsumedWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError(
                                                           "PumpConfigurationAndControl LifetimeEnergyConsumed write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed()
        : SubscribeAttribute("lifetime-energy-consumed")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLifetimeEnergyConsumedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.LifetimeEnergyConsumed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OperationMode
 */
class ReadPumpConfigurationAndControlOperationMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlOperationMode()
        : ReadAttribute("operation-mode")
    {
    }

    ~ReadPumpConfigurationAndControlOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeOperationModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.OperationMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl OperationMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlOperationMode : public WriteAttribute {
public:
    WritePumpConfigurationAndControlOperationMode()
        : WriteAttribute("operation-mode")
    {
        AddArgument("attr-name", "operation-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOperationModeWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("PumpConfigurationAndControl OperationMode write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlOperationMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlOperationMode()
        : SubscribeAttribute("operation-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOperationModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.OperationMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ControlMode
 */
class ReadPumpConfigurationAndControlControlMode : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlControlMode()
        : ReadAttribute("control-mode")
    {
    }

    ~ReadPumpConfigurationAndControlControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeControlModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.ControlMode response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl ControlMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WritePumpConfigurationAndControlControlMode : public WriteAttribute {
public:
    WritePumpConfigurationAndControlControlMode()
        : WriteAttribute("control-mode")
    {
        AddArgument("attr-name", "control-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WritePumpConfigurationAndControlControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeControlModeWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("PumpConfigurationAndControl ControlMode write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributePumpConfigurationAndControlControlMode : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlControlMode()
        : SubscribeAttribute("control-mode")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlControlMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeControlModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.ControlMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPumpConfigurationAndControlGeneratedCommandList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPumpConfigurationAndControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPumpConfigurationAndControlAcceptedCommandList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPumpConfigurationAndControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPumpConfigurationAndControlAttributeList : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPumpConfigurationAndControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPumpConfigurationAndControlFeatureMap : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPumpConfigurationAndControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPumpConfigurationAndControlClusterRevision : public ReadAttribute {
public:
    ReadPumpConfigurationAndControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPumpConfigurationAndControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PumpConfigurationAndControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PumpConfigurationAndControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePumpConfigurationAndControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePumpConfigurationAndControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePumpConfigurationAndControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000200) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPumpConfigurationAndControl * cluster =
            [[MTRBaseClusterPumpConfigurationAndControl alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PumpConfigurationAndControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Thermostat                                                  | 0x0201 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SetpointRaiseLower                                                |   0x00 |
| * SetWeeklySchedule                                                 |   0x01 |
| * GetWeeklySchedule                                                 |   0x02 |
| * ClearWeeklySchedule                                               |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * LocalTemperature                                                  | 0x0000 |
| * OutdoorTemperature                                                | 0x0001 |
| * Occupancy                                                         | 0x0002 |
| * AbsMinHeatSetpointLimit                                           | 0x0003 |
| * AbsMaxHeatSetpointLimit                                           | 0x0004 |
| * AbsMinCoolSetpointLimit                                           | 0x0005 |
| * AbsMaxCoolSetpointLimit                                           | 0x0006 |
| * PICoolingDemand                                                   | 0x0007 |
| * PIHeatingDemand                                                   | 0x0008 |
| * HVACSystemTypeConfiguration                                       | 0x0009 |
| * LocalTemperatureCalibration                                       | 0x0010 |
| * OccupiedCoolingSetpoint                                           | 0x0011 |
| * OccupiedHeatingSetpoint                                           | 0x0012 |
| * UnoccupiedCoolingSetpoint                                         | 0x0013 |
| * UnoccupiedHeatingSetpoint                                         | 0x0014 |
| * MinHeatSetpointLimit                                              | 0x0015 |
| * MaxHeatSetpointLimit                                              | 0x0016 |
| * MinCoolSetpointLimit                                              | 0x0017 |
| * MaxCoolSetpointLimit                                              | 0x0018 |
| * MinSetpointDeadBand                                               | 0x0019 |
| * RemoteSensing                                                     | 0x001A |
| * ControlSequenceOfOperation                                        | 0x001B |
| * SystemMode                                                        | 0x001C |
| * ThermostatRunningMode                                             | 0x001E |
| * StartOfWeek                                                       | 0x0020 |
| * NumberOfWeeklyTransitions                                         | 0x0021 |
| * NumberOfDailyTransitions                                          | 0x0022 |
| * TemperatureSetpointHold                                           | 0x0023 |
| * TemperatureSetpointHoldDuration                                   | 0x0024 |
| * ThermostatProgrammingOperationMode                                | 0x0025 |
| * ThermostatRunningState                                            | 0x0029 |
| * SetpointChangeSource                                              | 0x0030 |
| * SetpointChangeAmount                                              | 0x0031 |
| * SetpointChangeSourceTimestamp                                     | 0x0032 |
| * OccupiedSetback                                                   | 0x0034 |
| * OccupiedSetbackMin                                                | 0x0035 |
| * OccupiedSetbackMax                                                | 0x0036 |
| * UnoccupiedSetback                                                 | 0x0037 |
| * UnoccupiedSetbackMin                                              | 0x0038 |
| * UnoccupiedSetbackMax                                              | 0x0039 |
| * EmergencyHeatDelta                                                | 0x003A |
| * ACType                                                            | 0x0040 |
| * ACCapacity                                                        | 0x0041 |
| * ACRefrigerantType                                                 | 0x0042 |
| * ACCompressorType                                                  | 0x0043 |
| * ACErrorCode                                                       | 0x0044 |
| * ACLouverPosition                                                  | 0x0045 |
| * ACCoilTemperature                                                 | 0x0046 |
| * ACCapacityformat                                                  | 0x0047 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SetpointRaiseLower
 */
class ThermostatSetpointRaiseLower : public ClusterCommand {
public:
    ThermostatSetpointRaiseLower()
        : ClusterCommand("setpoint-raise-lower")
    {
        AddArgument("Mode", 0, UINT8_MAX, &mRequest.mode);
        AddArgument("Amount", INT8_MIN, INT8_MAX, &mRequest.amount);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRThermostatClusterSetpointRaiseLowerParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.mode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.mode)];
        params.amount = [NSNumber numberWithChar:mRequest.amount];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setpointRaiseLowerWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Thermostat::Commands::SetpointRaiseLower::Type mRequest;
};

/*
 * Command SetWeeklySchedule
 */
class ThermostatSetWeeklySchedule : public ClusterCommand {
public:
    ThermostatSetWeeklySchedule()
        : ClusterCommand("set-weekly-schedule")
        , mComplex_Transitions(&mRequest.transitions)
    {
        AddArgument("NumberOfTransitionsForSequence", 0, UINT8_MAX, &mRequest.numberOfTransitionsForSequence);
        AddArgument("DayOfWeekForSequence", 0, UINT8_MAX, &mRequest.dayOfWeekForSequence);
        AddArgument("ModeForSequence", 0, UINT8_MAX, &mRequest.modeForSequence);
        AddArgument("Transitions", &mComplex_Transitions);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRThermostatClusterSetWeeklyScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.numberOfTransitionsForSequence = [NSNumber numberWithUnsignedChar:mRequest.numberOfTransitionsForSequence];
        params.dayOfWeekForSequence = [NSNumber numberWithUnsignedChar:mRequest.dayOfWeekForSequence.Raw()];
        params.modeForSequence = [NSNumber numberWithUnsignedChar:mRequest.modeForSequence.Raw()];
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.transitions) {
                MTRThermostatClusterThermostatScheduleTransition * newElement_0;
                newElement_0 = [MTRThermostatClusterThermostatScheduleTransition new];
                newElement_0.transitionTime = [NSNumber numberWithUnsignedShort:entry_0.transitionTime];
                if (entry_0.heatSetpoint.IsNull()) {
                    newElement_0.heatSetpoint = nil;
                } else {
                    newElement_0.heatSetpoint = [NSNumber numberWithShort:entry_0.heatSetpoint.Value()];
                }
                if (entry_0.coolSetpoint.IsNull()) {
                    newElement_0.coolSetpoint = nil;
                } else {
                    newElement_0.coolSetpoint = [NSNumber numberWithShort:entry_0.coolSetpoint.Value()];
                }
                [array_0 addObject:newElement_0];
            }
            params.transitions = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster setWeeklyScheduleWithParams:params
                                      completion:^(NSError * _Nullable error) {
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Thermostat::Commands::SetWeeklySchedule::Type mRequest;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::Thermostat::Structs::ThermostatScheduleTransition::Type>>
        mComplex_Transitions;
};

/*
 * Command GetWeeklySchedule
 */
class ThermostatGetWeeklySchedule : public ClusterCommand {
public:
    ThermostatGetWeeklySchedule()
        : ClusterCommand("get-weekly-schedule")
    {
        AddArgument("DaysToReturn", 0, UINT8_MAX, &mRequest.daysToReturn);
        AddArgument("ModeToReturn", 0, UINT8_MAX, &mRequest.modeToReturn);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRThermostatClusterGetWeeklyScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.daysToReturn = [NSNumber numberWithUnsignedChar:mRequest.daysToReturn.Raw()];
        params.modeToReturn = [NSNumber numberWithUnsignedChar:mRequest.modeToReturn.Raw()];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getWeeklyScheduleWithParams:params
                                      completion:^(MTRThermostatClusterGetWeeklyScheduleResponseParams * _Nullable values,
                                          NSError * _Nullable error) {
                                          NSLog(@"Values: %@", values);
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Thermostat::Commands::GetWeeklySchedule::Type mRequest;
};

/*
 * Command ClearWeeklySchedule
 */
class ThermostatClearWeeklySchedule : public ClusterCommand {
public:
    ThermostatClearWeeklySchedule()
        : ClusterCommand("clear-weekly-schedule")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRThermostatClusterClearWeeklyScheduleParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster clearWeeklyScheduleWithParams:params
                                        completion:^(NSError * _Nullable error) {
                                            responsesNeeded--;
                                            if (error != nil) {
                                                mError = error;
                                                LogNSError("Error", error);
                                            }
                                            if (responsesNeeded == 0) {
                                                SetCommandExitStatus(mError);
                                            }
                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute LocalTemperature
 */
class ReadThermostatLocalTemperature : public ReadAttribute {
public:
    ReadThermostatLocalTemperature()
        : ReadAttribute("local-temperature")
    {
    }

    ~ReadThermostatLocalTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeLocalTemperatureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.LocalTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat LocalTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatLocalTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatLocalTemperature()
        : SubscribeAttribute("local-temperature")
    {
    }

    ~SubscribeAttributeThermostatLocalTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLocalTemperatureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.LocalTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OutdoorTemperature
 */
class ReadThermostatOutdoorTemperature : public ReadAttribute {
public:
    ReadThermostatOutdoorTemperature()
        : ReadAttribute("outdoor-temperature")
    {
    }

    ~ReadThermostatOutdoorTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOutdoorTemperatureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OutdoorTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OutdoorTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOutdoorTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOutdoorTemperature()
        : SubscribeAttribute("outdoor-temperature")
    {
    }

    ~SubscribeAttributeThermostatOutdoorTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOutdoorTemperatureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OutdoorTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Occupancy
 */
class ReadThermostatOccupancy : public ReadAttribute {
public:
    ReadThermostatOccupancy()
        : ReadAttribute("occupancy")
    {
    }

    ~ReadThermostatOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupancyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.Occupancy response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat Occupancy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOccupancy : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupancy()
        : SubscribeAttribute("occupancy")
    {
    }

    ~SubscribeAttributeThermostatOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupancyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.Occupancy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMinHeatSetpointLimit
 */
class ReadThermostatAbsMinHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMinHeatSetpointLimit()
        : ReadAttribute("abs-min-heat-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAbsMinHeatSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AbsMinHeatSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AbsMinHeatSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMinHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMinHeatSetpointLimit()
        : SubscribeAttribute("abs-min-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAbsMinHeatSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMinHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMaxHeatSetpointLimit
 */
class ReadThermostatAbsMaxHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMaxHeatSetpointLimit()
        : ReadAttribute("abs-max-heat-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAbsMaxHeatSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AbsMaxHeatSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AbsMaxHeatSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMaxHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMaxHeatSetpointLimit()
        : SubscribeAttribute("abs-max-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAbsMaxHeatSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMaxHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMinCoolSetpointLimit
 */
class ReadThermostatAbsMinCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMinCoolSetpointLimit()
        : ReadAttribute("abs-min-cool-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAbsMinCoolSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AbsMinCoolSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AbsMinCoolSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMinCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMinCoolSetpointLimit()
        : SubscribeAttribute("abs-min-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAbsMinCoolSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMinCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AbsMaxCoolSetpointLimit
 */
class ReadThermostatAbsMaxCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatAbsMaxCoolSetpointLimit()
        : ReadAttribute("abs-max-cool-setpoint-limit")
    {
    }

    ~ReadThermostatAbsMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAbsMaxCoolSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AbsMaxCoolSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AbsMaxCoolSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAbsMaxCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAbsMaxCoolSetpointLimit()
        : SubscribeAttribute("abs-max-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatAbsMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAbsMaxCoolSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AbsMaxCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PICoolingDemand
 */
class ReadThermostatPICoolingDemand : public ReadAttribute {
public:
    ReadThermostatPICoolingDemand()
        : ReadAttribute("picooling-demand")
    {
    }

    ~ReadThermostatPICoolingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributePICoolingDemandWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.PICoolingDemand response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat PICoolingDemand read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatPICoolingDemand : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatPICoolingDemand()
        : SubscribeAttribute("picooling-demand")
    {
    }

    ~SubscribeAttributeThermostatPICoolingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePICoolingDemandWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.PICoolingDemand response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PIHeatingDemand
 */
class ReadThermostatPIHeatingDemand : public ReadAttribute {
public:
    ReadThermostatPIHeatingDemand()
        : ReadAttribute("piheating-demand")
    {
    }

    ~ReadThermostatPIHeatingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributePIHeatingDemandWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.PIHeatingDemand response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat PIHeatingDemand read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatPIHeatingDemand : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatPIHeatingDemand()
        : SubscribeAttribute("piheating-demand")
    {
    }

    ~SubscribeAttributeThermostatPIHeatingDemand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePIHeatingDemandWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.PIHeatingDemand response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HVACSystemTypeConfiguration
 */
class ReadThermostatHVACSystemTypeConfiguration : public ReadAttribute {
public:
    ReadThermostatHVACSystemTypeConfiguration()
        : ReadAttribute("hvacsystem-type-configuration")
    {
    }

    ~ReadThermostatHVACSystemTypeConfiguration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeHVACSystemTypeConfigurationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.HVACSystemTypeConfiguration response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat HVACSystemTypeConfiguration read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatHVACSystemTypeConfiguration : public WriteAttribute {
public:
    WriteThermostatHVACSystemTypeConfiguration()
        : WriteAttribute("hvacsystem-type-configuration")
    {
        AddArgument("attr-name", "hvacsystem-type-configuration");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatHVACSystemTypeConfiguration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeHVACSystemTypeConfigurationWithValue:value
                                                        params:params
                                                    completion:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError("Thermostat HVACSystemTypeConfiguration write Error", error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatHVACSystemTypeConfiguration : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatHVACSystemTypeConfiguration()
        : SubscribeAttribute("hvacsystem-type-configuration")
    {
    }

    ~SubscribeAttributeThermostatHVACSystemTypeConfiguration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHVACSystemTypeConfigurationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.HVACSystemTypeConfiguration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LocalTemperatureCalibration
 */
class ReadThermostatLocalTemperatureCalibration : public ReadAttribute {
public:
    ReadThermostatLocalTemperatureCalibration()
        : ReadAttribute("local-temperature-calibration")
    {
    }

    ~ReadThermostatLocalTemperatureCalibration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeLocalTemperatureCalibrationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.LocalTemperatureCalibration response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat LocalTemperatureCalibration read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatLocalTemperatureCalibration : public WriteAttribute {
public:
    WriteThermostatLocalTemperatureCalibration()
        : WriteAttribute("local-temperature-calibration")
    {
        AddArgument("attr-name", "local-temperature-calibration");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatLocalTemperatureCalibration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster
            writeAttributeLocalTemperatureCalibrationWithValue:value
                                                        params:params
                                                    completion:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError("Thermostat LocalTemperatureCalibration write Error", error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeThermostatLocalTemperatureCalibration : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatLocalTemperatureCalibration()
        : SubscribeAttribute("local-temperature-calibration")
    {
    }

    ~SubscribeAttributeThermostatLocalTemperatureCalibration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLocalTemperatureCalibrationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.LocalTemperatureCalibration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedCoolingSetpoint
 */
class ReadThermostatOccupiedCoolingSetpoint : public ReadAttribute {
public:
    ReadThermostatOccupiedCoolingSetpoint()
        : ReadAttribute("occupied-cooling-setpoint")
    {
    }

    ~ReadThermostatOccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedCoolingSetpointWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedCoolingSetpoint response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedCoolingSetpoint read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatOccupiedCoolingSetpoint : public WriteAttribute {
public:
    WriteThermostatOccupiedCoolingSetpoint()
        : WriteAttribute("occupied-cooling-setpoint")
    {
        AddArgument("attr-name", "occupied-cooling-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatOccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeOccupiedCoolingSetpointWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("Thermostat OccupiedCoolingSetpoint write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatOccupiedCoolingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedCoolingSetpoint()
        : SubscribeAttribute("occupied-cooling-setpoint")
    {
    }

    ~SubscribeAttributeThermostatOccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupiedCoolingSetpointWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedCoolingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedHeatingSetpoint
 */
class ReadThermostatOccupiedHeatingSetpoint : public ReadAttribute {
public:
    ReadThermostatOccupiedHeatingSetpoint()
        : ReadAttribute("occupied-heating-setpoint")
    {
    }

    ~ReadThermostatOccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedHeatingSetpointWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedHeatingSetpoint response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedHeatingSetpoint read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatOccupiedHeatingSetpoint : public WriteAttribute {
public:
    WriteThermostatOccupiedHeatingSetpoint()
        : WriteAttribute("occupied-heating-setpoint")
    {
        AddArgument("attr-name", "occupied-heating-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatOccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeOccupiedHeatingSetpointWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("Thermostat OccupiedHeatingSetpoint write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatOccupiedHeatingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedHeatingSetpoint()
        : SubscribeAttribute("occupied-heating-setpoint")
    {
    }

    ~SubscribeAttributeThermostatOccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupiedHeatingSetpointWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedHeatingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedCoolingSetpoint
 */
class ReadThermostatUnoccupiedCoolingSetpoint : public ReadAttribute {
public:
    ReadThermostatUnoccupiedCoolingSetpoint()
        : ReadAttribute("unoccupied-cooling-setpoint")
    {
    }

    ~ReadThermostatUnoccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedCoolingSetpointWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedCoolingSetpoint response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedCoolingSetpoint read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUnoccupiedCoolingSetpoint : public WriteAttribute {
public:
    WriteThermostatUnoccupiedCoolingSetpoint()
        : WriteAttribute("unoccupied-cooling-setpoint")
    {
        AddArgument("attr-name", "unoccupied-cooling-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUnoccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster
            writeAttributeUnoccupiedCoolingSetpointWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat UnoccupiedCoolingSetpoint write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatUnoccupiedCoolingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedCoolingSetpoint()
        : SubscribeAttribute("unoccupied-cooling-setpoint")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedCoolingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUnoccupiedCoolingSetpointWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedCoolingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedHeatingSetpoint
 */
class ReadThermostatUnoccupiedHeatingSetpoint : public ReadAttribute {
public:
    ReadThermostatUnoccupiedHeatingSetpoint()
        : ReadAttribute("unoccupied-heating-setpoint")
    {
    }

    ~ReadThermostatUnoccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedHeatingSetpointWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedHeatingSetpoint response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedHeatingSetpoint read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUnoccupiedHeatingSetpoint : public WriteAttribute {
public:
    WriteThermostatUnoccupiedHeatingSetpoint()
        : WriteAttribute("unoccupied-heating-setpoint")
    {
        AddArgument("attr-name", "unoccupied-heating-setpoint");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUnoccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster
            writeAttributeUnoccupiedHeatingSetpointWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat UnoccupiedHeatingSetpoint write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatUnoccupiedHeatingSetpoint : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedHeatingSetpoint()
        : SubscribeAttribute("unoccupied-heating-setpoint")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedHeatingSetpoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUnoccupiedHeatingSetpointWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedHeatingSetpoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinHeatSetpointLimit
 */
class ReadThermostatMinHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMinHeatSetpointLimit()
        : ReadAttribute("min-heat-setpoint-limit")
    {
    }

    ~ReadThermostatMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeMinHeatSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MinHeatSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MinHeatSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMinHeatSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMinHeatSetpointLimit()
        : WriteAttribute("min-heat-setpoint-limit")
    {
        AddArgument("attr-name", "min-heat-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMinHeatSetpointLimitWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat MinHeatSetpointLimit write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMinHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMinHeatSetpointLimit()
        : SubscribeAttribute("min-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMinHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinHeatSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MinHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxHeatSetpointLimit
 */
class ReadThermostatMaxHeatSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMaxHeatSetpointLimit()
        : ReadAttribute("max-heat-setpoint-limit")
    {
    }

    ~ReadThermostatMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxHeatSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MaxHeatSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MaxHeatSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMaxHeatSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMaxHeatSetpointLimit()
        : WriteAttribute("max-heat-setpoint-limit")
    {
        AddArgument("attr-name", "max-heat-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMaxHeatSetpointLimitWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat MaxHeatSetpointLimit write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMaxHeatSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMaxHeatSetpointLimit()
        : SubscribeAttribute("max-heat-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMaxHeatSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxHeatSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MaxHeatSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinCoolSetpointLimit
 */
class ReadThermostatMinCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMinCoolSetpointLimit()
        : ReadAttribute("min-cool-setpoint-limit")
    {
    }

    ~ReadThermostatMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeMinCoolSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MinCoolSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MinCoolSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMinCoolSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMinCoolSetpointLimit()
        : WriteAttribute("min-cool-setpoint-limit")
    {
        AddArgument("attr-name", "min-cool-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMinCoolSetpointLimitWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat MinCoolSetpointLimit write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMinCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMinCoolSetpointLimit()
        : SubscribeAttribute("min-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMinCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinCoolSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MinCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxCoolSetpointLimit
 */
class ReadThermostatMaxCoolSetpointLimit : public ReadAttribute {
public:
    ReadThermostatMaxCoolSetpointLimit()
        : ReadAttribute("max-cool-setpoint-limit")
    {
    }

    ~ReadThermostatMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeMaxCoolSetpointLimitWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MaxCoolSetpointLimit response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MaxCoolSetpointLimit read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMaxCoolSetpointLimit : public WriteAttribute {
public:
    WriteThermostatMaxCoolSetpointLimit()
        : WriteAttribute("max-cool-setpoint-limit")
    {
        AddArgument("attr-name", "max-cool-setpoint-limit");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeMaxCoolSetpointLimitWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("Thermostat MaxCoolSetpointLimit write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeThermostatMaxCoolSetpointLimit : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMaxCoolSetpointLimit()
        : SubscribeAttribute("max-cool-setpoint-limit")
    {
    }

    ~SubscribeAttributeThermostatMaxCoolSetpointLimit() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxCoolSetpointLimitWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MaxCoolSetpointLimit response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinSetpointDeadBand
 */
class ReadThermostatMinSetpointDeadBand : public ReadAttribute {
public:
    ReadThermostatMinSetpointDeadBand()
        : ReadAttribute("min-setpoint-dead-band")
    {
    }

    ~ReadThermostatMinSetpointDeadBand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeMinSetpointDeadBandWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.MinSetpointDeadBand response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat MinSetpointDeadBand read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatMinSetpointDeadBand : public WriteAttribute {
public:
    WriteThermostatMinSetpointDeadBand()
        : WriteAttribute("min-setpoint-dead-band")
    {
        AddArgument("attr-name", "min-setpoint-dead-band");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatMinSetpointDeadBand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeMinSetpointDeadBandWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("Thermostat MinSetpointDeadBand write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeThermostatMinSetpointDeadBand : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatMinSetpointDeadBand()
        : SubscribeAttribute("min-setpoint-dead-band")
    {
    }

    ~SubscribeAttributeThermostatMinSetpointDeadBand() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinSetpointDeadBandWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.MinSetpointDeadBand response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RemoteSensing
 */
class ReadThermostatRemoteSensing : public ReadAttribute {
public:
    ReadThermostatRemoteSensing()
        : ReadAttribute("remote-sensing")
    {
    }

    ~ReadThermostatRemoteSensing() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeRemoteSensingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.RemoteSensing response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat RemoteSensing read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatRemoteSensing : public WriteAttribute {
public:
    WriteThermostatRemoteSensing()
        : WriteAttribute("remote-sensing")
    {
        AddArgument("attr-name", "remote-sensing");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatRemoteSensing() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRemoteSensingWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("Thermostat RemoteSensing write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatRemoteSensing : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatRemoteSensing()
        : SubscribeAttribute("remote-sensing")
    {
    }

    ~SubscribeAttributeThermostatRemoteSensing() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRemoteSensingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.RemoteSensing response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ControlSequenceOfOperation
 */
class ReadThermostatControlSequenceOfOperation : public ReadAttribute {
public:
    ReadThermostatControlSequenceOfOperation()
        : ReadAttribute("control-sequence-of-operation")
    {
    }

    ~ReadThermostatControlSequenceOfOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeControlSequenceOfOperationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ControlSequenceOfOperation response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ControlSequenceOfOperation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatControlSequenceOfOperation : public WriteAttribute {
public:
    WriteThermostatControlSequenceOfOperation()
        : WriteAttribute("control-sequence-of-operation")
    {
        AddArgument("attr-name", "control-sequence-of-operation");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatControlSequenceOfOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeControlSequenceOfOperationWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("Thermostat ControlSequenceOfOperation write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatControlSequenceOfOperation : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatControlSequenceOfOperation()
        : SubscribeAttribute("control-sequence-of-operation")
    {
    }

    ~SubscribeAttributeThermostatControlSequenceOfOperation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeControlSequenceOfOperationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ControlSequenceOfOperation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SystemMode
 */
class ReadThermostatSystemMode : public ReadAttribute {
public:
    ReadThermostatSystemMode()
        : ReadAttribute("system-mode")
    {
    }

    ~ReadThermostatSystemMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSystemModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SystemMode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SystemMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatSystemMode : public WriteAttribute {
public:
    WriteThermostatSystemMode()
        : WriteAttribute("system-mode")
    {
        AddArgument("attr-name", "system-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatSystemMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSystemModeWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("Thermostat SystemMode write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatSystemMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSystemMode()
        : SubscribeAttribute("system-mode")
    {
    }

    ~SubscribeAttributeThermostatSystemMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSystemModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SystemMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ThermostatRunningMode
 */
class ReadThermostatThermostatRunningMode : public ReadAttribute {
public:
    ReadThermostatThermostatRunningMode()
        : ReadAttribute("thermostat-running-mode")
    {
    }

    ~ReadThermostatThermostatRunningMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeThermostatRunningModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ThermostatRunningMode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ThermostatRunningMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatThermostatRunningMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatThermostatRunningMode()
        : SubscribeAttribute("thermostat-running-mode")
    {
    }

    ~SubscribeAttributeThermostatThermostatRunningMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeThermostatRunningModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatRunningMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartOfWeek
 */
class ReadThermostatStartOfWeek : public ReadAttribute {
public:
    ReadThermostatStartOfWeek()
        : ReadAttribute("start-of-week")
    {
    }

    ~ReadThermostatStartOfWeek() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeStartOfWeekWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.StartOfWeek response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat StartOfWeek read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatStartOfWeek : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatStartOfWeek()
        : SubscribeAttribute("start-of-week")
    {
    }

    ~SubscribeAttributeThermostatStartOfWeek() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStartOfWeekWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.StartOfWeek response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfWeeklyTransitions
 */
class ReadThermostatNumberOfWeeklyTransitions : public ReadAttribute {
public:
    ReadThermostatNumberOfWeeklyTransitions()
        : ReadAttribute("number-of-weekly-transitions")
    {
    }

    ~ReadThermostatNumberOfWeeklyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeNumberOfWeeklyTransitionsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.NumberOfWeeklyTransitions response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat NumberOfWeeklyTransitions read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatNumberOfWeeklyTransitions : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatNumberOfWeeklyTransitions()
        : SubscribeAttribute("number-of-weekly-transitions")
    {
    }

    ~SubscribeAttributeThermostatNumberOfWeeklyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfWeeklyTransitionsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.NumberOfWeeklyTransitions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfDailyTransitions
 */
class ReadThermostatNumberOfDailyTransitions : public ReadAttribute {
public:
    ReadThermostatNumberOfDailyTransitions()
        : ReadAttribute("number-of-daily-transitions")
    {
    }

    ~ReadThermostatNumberOfDailyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeNumberOfDailyTransitionsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.NumberOfDailyTransitions response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat NumberOfDailyTransitions read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatNumberOfDailyTransitions : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatNumberOfDailyTransitions()
        : SubscribeAttribute("number-of-daily-transitions")
    {
    }

    ~SubscribeAttributeThermostatNumberOfDailyTransitions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfDailyTransitionsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.NumberOfDailyTransitions response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TemperatureSetpointHold
 */
class ReadThermostatTemperatureSetpointHold : public ReadAttribute {
public:
    ReadThermostatTemperatureSetpointHold()
        : ReadAttribute("temperature-setpoint-hold")
    {
    }

    ~ReadThermostatTemperatureSetpointHold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeTemperatureSetpointHoldWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.TemperatureSetpointHold response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat TemperatureSetpointHold read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatTemperatureSetpointHold : public WriteAttribute {
public:
    WriteThermostatTemperatureSetpointHold()
        : WriteAttribute("temperature-setpoint-hold")
    {
        AddArgument("attr-name", "temperature-setpoint-hold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatTemperatureSetpointHold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeTemperatureSetpointHoldWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("Thermostat TemperatureSetpointHold write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatTemperatureSetpointHold : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatTemperatureSetpointHold()
        : SubscribeAttribute("temperature-setpoint-hold")
    {
    }

    ~SubscribeAttributeThermostatTemperatureSetpointHold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTemperatureSetpointHoldWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.TemperatureSetpointHold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TemperatureSetpointHoldDuration
 */
class ReadThermostatTemperatureSetpointHoldDuration : public ReadAttribute {
public:
    ReadThermostatTemperatureSetpointHoldDuration()
        : ReadAttribute("temperature-setpoint-hold-duration")
    {
    }

    ~ReadThermostatTemperatureSetpointHoldDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeTemperatureSetpointHoldDurationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.TemperatureSetpointHoldDuration response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat TemperatureSetpointHoldDuration read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatTemperatureSetpointHoldDuration : public WriteAttribute {
public:
    WriteThermostatTemperatureSetpointHoldDuration()
        : WriteAttribute("temperature-setpoint-hold-duration")
    {
        AddArgument("attr-name", "temperature-setpoint-hold-duration");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatTemperatureSetpointHoldDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeTemperatureSetpointHoldDurationWithValue:value
                                                            params:params
                                                        completion:^(NSError * _Nullable error) {
                                                            if (error != nil) {
                                                                LogNSError("Thermostat TemperatureSetpointHoldDuration write Error",
                                                                    error);
                                                            }
                                                            SetCommandExitStatus(error);
                                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeThermostatTemperatureSetpointHoldDuration : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatTemperatureSetpointHoldDuration()
        : SubscribeAttribute("temperature-setpoint-hold-duration")
    {
    }

    ~SubscribeAttributeThermostatTemperatureSetpointHoldDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTemperatureSetpointHoldDurationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.TemperatureSetpointHoldDuration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ThermostatProgrammingOperationMode
 */
class ReadThermostatThermostatProgrammingOperationMode : public ReadAttribute {
public:
    ReadThermostatThermostatProgrammingOperationMode()
        : ReadAttribute("thermostat-programming-operation-mode")
    {
    }

    ~ReadThermostatThermostatProgrammingOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster
            readAttributeThermostatProgrammingOperationModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatProgrammingOperationMode response %@", [value description]);
                if (error != nil) {
                    LogNSError("Thermostat ThermostatProgrammingOperationMode read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatThermostatProgrammingOperationMode : public WriteAttribute {
public:
    WriteThermostatThermostatProgrammingOperationMode()
        : WriteAttribute("thermostat-programming-operation-mode")
    {
        AddArgument("attr-name", "thermostat-programming-operation-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatThermostatProgrammingOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeThermostatProgrammingOperationModeWithValue:value
                                                               params:params
                                                           completion:^(NSError * _Nullable error) {
                                                               if (error != nil) {
                                                                   LogNSError(
                                                                       "Thermostat ThermostatProgrammingOperationMode write Error",
                                                                       error);
                                                               }
                                                               SetCommandExitStatus(error);
                                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatThermostatProgrammingOperationMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatThermostatProgrammingOperationMode()
        : SubscribeAttribute("thermostat-programming-operation-mode")
    {
    }

    ~SubscribeAttributeThermostatThermostatProgrammingOperationMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeThermostatProgrammingOperationModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatProgrammingOperationMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ThermostatRunningState
 */
class ReadThermostatThermostatRunningState : public ReadAttribute {
public:
    ReadThermostatThermostatRunningState()
        : ReadAttribute("thermostat-running-state")
    {
    }

    ~ReadThermostatThermostatRunningState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeThermostatRunningStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ThermostatRunningState response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ThermostatRunningState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatThermostatRunningState : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatThermostatRunningState()
        : SubscribeAttribute("thermostat-running-state")
    {
    }

    ~SubscribeAttributeThermostatThermostatRunningState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeThermostatRunningStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ThermostatRunningState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetpointChangeSource
 */
class ReadThermostatSetpointChangeSource : public ReadAttribute {
public:
    ReadThermostatSetpointChangeSource()
        : ReadAttribute("setpoint-change-source")
    {
    }

    ~ReadThermostatSetpointChangeSource() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSetpointChangeSourceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SetpointChangeSource response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SetpointChangeSource read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatSetpointChangeSource : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSetpointChangeSource()
        : SubscribeAttribute("setpoint-change-source")
    {
    }

    ~SubscribeAttributeThermostatSetpointChangeSource() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSetpointChangeSourceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SetpointChangeSource response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetpointChangeAmount
 */
class ReadThermostatSetpointChangeAmount : public ReadAttribute {
public:
    ReadThermostatSetpointChangeAmount()
        : ReadAttribute("setpoint-change-amount")
    {
    }

    ~ReadThermostatSetpointChangeAmount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSetpointChangeAmountWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SetpointChangeAmount response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SetpointChangeAmount read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatSetpointChangeAmount : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSetpointChangeAmount()
        : SubscribeAttribute("setpoint-change-amount")
    {
    }

    ~SubscribeAttributeThermostatSetpointChangeAmount() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSetpointChangeAmountWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SetpointChangeAmount response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SetpointChangeSourceTimestamp
 */
class ReadThermostatSetpointChangeSourceTimestamp : public ReadAttribute {
public:
    ReadThermostatSetpointChangeSourceTimestamp()
        : ReadAttribute("setpoint-change-source-timestamp")
    {
    }

    ~ReadThermostatSetpointChangeSourceTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSetpointChangeSourceTimestampWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.SetpointChangeSourceTimestamp response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat SetpointChangeSourceTimestamp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatSetpointChangeSourceTimestamp : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatSetpointChangeSourceTimestamp()
        : SubscribeAttribute("setpoint-change-source-timestamp")
    {
    }

    ~SubscribeAttributeThermostatSetpointChangeSourceTimestamp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSetpointChangeSourceTimestampWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.SetpointChangeSourceTimestamp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedSetback
 */
class ReadThermostatOccupiedSetback : public ReadAttribute {
public:
    ReadThermostatOccupiedSetback()
        : ReadAttribute("occupied-setback")
    {
    }

    ~ReadThermostatOccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedSetbackWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedSetback response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedSetback read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatOccupiedSetback : public WriteAttribute {
public:
    WriteThermostatOccupiedSetback()
        : WriteAttribute("occupied-setback")
    {
        AddArgument("attr-name", "occupied-setback");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatOccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOccupiedSetbackWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("Thermostat OccupiedSetback write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatOccupiedSetback : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedSetback()
        : SubscribeAttribute("occupied-setback")
    {
    }

    ~SubscribeAttributeThermostatOccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupiedSetbackWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedSetback response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedSetbackMin
 */
class ReadThermostatOccupiedSetbackMin : public ReadAttribute {
public:
    ReadThermostatOccupiedSetbackMin()
        : ReadAttribute("occupied-setback-min")
    {
    }

    ~ReadThermostatOccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedSetbackMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedSetbackMin response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedSetbackMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOccupiedSetbackMin : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedSetbackMin()
        : SubscribeAttribute("occupied-setback-min")
    {
    }

    ~SubscribeAttributeThermostatOccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupiedSetbackMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedSetbackMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupiedSetbackMax
 */
class ReadThermostatOccupiedSetbackMax : public ReadAttribute {
public:
    ReadThermostatOccupiedSetbackMax()
        : ReadAttribute("occupied-setback-max")
    {
    }

    ~ReadThermostatOccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000036) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeOccupiedSetbackMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.OccupiedSetbackMax response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat OccupiedSetbackMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatOccupiedSetbackMax : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatOccupiedSetbackMax()
        : SubscribeAttribute("occupied-setback-max")
    {
    }

    ~SubscribeAttributeThermostatOccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupiedSetbackMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.OccupiedSetbackMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedSetback
 */
class ReadThermostatUnoccupiedSetback : public ReadAttribute {
public:
    ReadThermostatUnoccupiedSetback()
        : ReadAttribute("unoccupied-setback")
    {
    }

    ~ReadThermostatUnoccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000037) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedSetbackWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedSetback response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedSetback read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUnoccupiedSetback : public WriteAttribute {
public:
    WriteThermostatUnoccupiedSetback()
        : WriteAttribute("unoccupied-setback")
    {
        AddArgument("attr-name", "unoccupied-setback");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUnoccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeUnoccupiedSetbackWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("Thermostat UnoccupiedSetback write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUnoccupiedSetback : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedSetback()
        : SubscribeAttribute("unoccupied-setback")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedSetback() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUnoccupiedSetbackWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedSetback response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedSetbackMin
 */
class ReadThermostatUnoccupiedSetbackMin : public ReadAttribute {
public:
    ReadThermostatUnoccupiedSetbackMin()
        : ReadAttribute("unoccupied-setback-min")
    {
    }

    ~ReadThermostatUnoccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000038) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedSetbackMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedSetbackMin response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedSetbackMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUnoccupiedSetbackMin : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedSetbackMin()
        : SubscribeAttribute("unoccupied-setback-min")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedSetbackMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUnoccupiedSetbackMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedSetbackMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UnoccupiedSetbackMax
 */
class ReadThermostatUnoccupiedSetbackMax : public ReadAttribute {
public:
    ReadThermostatUnoccupiedSetbackMax()
        : ReadAttribute("unoccupied-setback-max")
    {
    }

    ~ReadThermostatUnoccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000039) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeUnoccupiedSetbackMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.UnoccupiedSetbackMax response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat UnoccupiedSetbackMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUnoccupiedSetbackMax : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUnoccupiedSetbackMax()
        : SubscribeAttribute("unoccupied-setback-max")
    {
    }

    ~SubscribeAttributeThermostatUnoccupiedSetbackMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000039) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUnoccupiedSetbackMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.UnoccupiedSetbackMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EmergencyHeatDelta
 */
class ReadThermostatEmergencyHeatDelta : public ReadAttribute {
public:
    ReadThermostatEmergencyHeatDelta()
        : ReadAttribute("emergency-heat-delta")
    {
    }

    ~ReadThermostatEmergencyHeatDelta() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000003A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeEmergencyHeatDeltaWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.EmergencyHeatDelta response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat EmergencyHeatDelta read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatEmergencyHeatDelta : public WriteAttribute {
public:
    WriteThermostatEmergencyHeatDelta()
        : WriteAttribute("emergency-heat-delta")
    {
        AddArgument("attr-name", "emergency-heat-delta");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatEmergencyHeatDelta() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEmergencyHeatDeltaWithValue:value
                                                    params:params
                                                completion:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("Thermostat EmergencyHeatDelta write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatEmergencyHeatDelta : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatEmergencyHeatDelta()
        : SubscribeAttribute("emergency-heat-delta")
    {
    }

    ~SubscribeAttributeThermostatEmergencyHeatDelta() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEmergencyHeatDeltaWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.EmergencyHeatDelta response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACType
 */
class ReadThermostatACType : public ReadAttribute {
public:
    ReadThermostatACType()
        : ReadAttribute("actype")
    {
    }

    ~ReadThermostatACType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACType response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACType : public WriteAttribute {
public:
    WriteThermostatACType()
        : WriteAttribute("actype")
    {
        AddArgument("attr-name", "actype");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000040) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACTypeWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("Thermostat ACType write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACType : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACType()
        : SubscribeAttribute("actype")
    {
    }

    ~SubscribeAttributeThermostatACType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000040) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCapacity
 */
class ReadThermostatACCapacity : public ReadAttribute {
public:
    ReadThermostatACCapacity()
        : ReadAttribute("accapacity")
    {
    }

    ~ReadThermostatACCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000041) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCapacityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCapacity response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCapacity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACCapacity : public WriteAttribute {
public:
    WriteThermostatACCapacity()
        : WriteAttribute("accapacity")
    {
        AddArgument("attr-name", "accapacity");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000041) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeACCapacityWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("Thermostat ACCapacity write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeThermostatACCapacity : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCapacity()
        : SubscribeAttribute("accapacity")
    {
    }

    ~SubscribeAttributeThermostatACCapacity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000041) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACCapacityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCapacity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACRefrigerantType
 */
class ReadThermostatACRefrigerantType : public ReadAttribute {
public:
    ReadThermostatACRefrigerantType()
        : ReadAttribute("acrefrigerant-type")
    {
    }

    ~ReadThermostatACRefrigerantType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000042) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACRefrigerantTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACRefrigerantType response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACRefrigerantType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACRefrigerantType : public WriteAttribute {
public:
    WriteThermostatACRefrigerantType()
        : WriteAttribute("acrefrigerant-type")
    {
        AddArgument("attr-name", "acrefrigerant-type");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACRefrigerantType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000042) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACRefrigerantTypeWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("Thermostat ACRefrigerantType write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACRefrigerantType : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACRefrigerantType()
        : SubscribeAttribute("acrefrigerant-type")
    {
    }

    ~SubscribeAttributeThermostatACRefrigerantType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000042) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACRefrigerantTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACRefrigerantType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCompressorType
 */
class ReadThermostatACCompressorType : public ReadAttribute {
public:
    ReadThermostatACCompressorType()
        : ReadAttribute("accompressor-type")
    {
    }

    ~ReadThermostatACCompressorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000043) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCompressorTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCompressorType response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCompressorType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACCompressorType : public WriteAttribute {
public:
    WriteThermostatACCompressorType()
        : WriteAttribute("accompressor-type")
    {
        AddArgument("attr-name", "accompressor-type");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACCompressorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000043) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACCompressorTypeWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("Thermostat ACCompressorType write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACCompressorType : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCompressorType()
        : SubscribeAttribute("accompressor-type")
    {
    }

    ~SubscribeAttributeThermostatACCompressorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000043) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACCompressorTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCompressorType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACErrorCode
 */
class ReadThermostatACErrorCode : public ReadAttribute {
public:
    ReadThermostatACErrorCode()
        : ReadAttribute("acerror-code")
    {
    }

    ~ReadThermostatACErrorCode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000044) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACErrorCodeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACErrorCode response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACErrorCode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACErrorCode : public WriteAttribute {
public:
    WriteThermostatACErrorCode()
        : WriteAttribute("acerror-code")
    {
        AddArgument("attr-name", "acerror-code");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACErrorCode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000044) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeACErrorCodeWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("Thermostat ACErrorCode write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeThermostatACErrorCode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACErrorCode()
        : SubscribeAttribute("acerror-code")
    {
    }

    ~SubscribeAttributeThermostatACErrorCode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000044) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACErrorCodeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACErrorCode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACLouverPosition
 */
class ReadThermostatACLouverPosition : public ReadAttribute {
public:
    ReadThermostatACLouverPosition()
        : ReadAttribute("aclouver-position")
    {
    }

    ~ReadThermostatACLouverPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000045) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACLouverPositionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACLouverPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACLouverPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACLouverPosition : public WriteAttribute {
public:
    WriteThermostatACLouverPosition()
        : WriteAttribute("aclouver-position")
    {
        AddArgument("attr-name", "aclouver-position");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACLouverPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000045) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACLouverPositionWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("Thermostat ACLouverPosition write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACLouverPosition : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACLouverPosition()
        : SubscribeAttribute("aclouver-position")
    {
    }

    ~SubscribeAttributeThermostatACLouverPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000045) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACLouverPositionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACLouverPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCoilTemperature
 */
class ReadThermostatACCoilTemperature : public ReadAttribute {
public:
    ReadThermostatACCoilTemperature()
        : ReadAttribute("accoil-temperature")
    {
    }

    ~ReadThermostatACCoilTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000046) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCoilTemperatureWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCoilTemperature response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCoilTemperature read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatACCoilTemperature : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCoilTemperature()
        : SubscribeAttribute("accoil-temperature")
    {
    }

    ~SubscribeAttributeThermostatACCoilTemperature() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000046) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACCoilTemperatureWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCoilTemperature response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ACCapacityformat
 */
class ReadThermostatACCapacityformat : public ReadAttribute {
public:
    ReadThermostatACCapacityformat()
        : ReadAttribute("accapacityformat")
    {
    }

    ~ReadThermostatACCapacityformat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x00000047) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeACCapacityformatWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ACCapacityformat response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ACCapacityformat read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatACCapacityformat : public WriteAttribute {
public:
    WriteThermostatACCapacityformat()
        : WriteAttribute("accapacityformat")
    {
        AddArgument("attr-name", "accapacityformat");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatACCapacityformat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) WriteAttribute (0x00000047) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeACCapacityformatWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("Thermostat ACCapacityformat write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatACCapacityformat : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatACCapacityformat()
        : SubscribeAttribute("accapacityformat")
    {
    }

    ~SubscribeAttributeThermostatACCapacityformat() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x00000047) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeACCapacityformatWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ACCapacityformat response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadThermostatGeneratedCommandList : public ReadAttribute {
public:
    ReadThermostatGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadThermostatGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeThermostatGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadThermostatAcceptedCommandList : public ReadAttribute {
public:
    ReadThermostatAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadThermostatAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeThermostatAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadThermostatAttributeList : public ReadAttribute {
public:
    ReadThermostatAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadThermostatAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeThermostatAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadThermostatFeatureMap : public ReadAttribute {
public:
    ReadThermostatFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadThermostatFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeThermostatFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadThermostatClusterRevision : public ReadAttribute {
public:
    ReadThermostatClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadThermostatClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Thermostat.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Thermostat ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeThermostatClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000201) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostat * cluster = [[MTRBaseClusterThermostat alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Thermostat.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FanControl                                                  | 0x0202 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * FanMode                                                           | 0x0000 |
| * FanModeSequence                                                   | 0x0001 |
| * PercentSetting                                                    | 0x0002 |
| * PercentCurrent                                                    | 0x0003 |
| * SpeedMax                                                          | 0x0004 |
| * SpeedSetting                                                      | 0x0005 |
| * SpeedCurrent                                                      | 0x0006 |
| * RockSupport                                                       | 0x0007 |
| * RockSetting                                                       | 0x0008 |
| * WindSupport                                                       | 0x0009 |
| * WindSetting                                                       | 0x000A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute FanMode
 */
class ReadFanControlFanMode : public ReadAttribute {
public:
    ReadFanControlFanMode()
        : ReadAttribute("fan-mode")
    {
    }

    ~ReadFanControlFanMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFanModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.FanMode response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl FanMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlFanMode : public WriteAttribute {
public:
    WriteFanControlFanMode()
        : WriteAttribute("fan-mode")
    {
        AddArgument("attr-name", "fan-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlFanMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeFanModeWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("FanControl FanMode write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlFanMode : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlFanMode()
        : SubscribeAttribute("fan-mode")
    {
    }

    ~SubscribeAttributeFanControlFanMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFanModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.FanMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FanModeSequence
 */
class ReadFanControlFanModeSequence : public ReadAttribute {
public:
    ReadFanControlFanModeSequence()
        : ReadAttribute("fan-mode-sequence")
    {
    }

    ~ReadFanControlFanModeSequence() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFanModeSequenceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.FanModeSequence response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl FanModeSequence read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlFanModeSequence : public WriteAttribute {
public:
    WriteFanControlFanModeSequence()
        : WriteAttribute("fan-mode-sequence")
    {
        AddArgument("attr-name", "fan-mode-sequence");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlFanModeSequence() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeFanModeSequenceWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("FanControl FanModeSequence write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlFanModeSequence : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlFanModeSequence()
        : SubscribeAttribute("fan-mode-sequence")
    {
    }

    ~SubscribeAttributeFanControlFanModeSequence() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFanModeSequenceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.FanModeSequence response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PercentSetting
 */
class ReadFanControlPercentSetting : public ReadAttribute {
public:
    ReadFanControlPercentSetting()
        : ReadAttribute("percent-setting")
    {
    }

    ~ReadFanControlPercentSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributePercentSettingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.PercentSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl PercentSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlPercentSetting : public WriteAttribute {
public:
    WriteFanControlPercentSetting()
        : WriteAttribute("percent-setting")
    {
        AddArgument("attr-name", "percent-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlPercentSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributePercentSettingWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("FanControl PercentSetting write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlPercentSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlPercentSetting()
        : SubscribeAttribute("percent-setting")
    {
    }

    ~SubscribeAttributeFanControlPercentSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePercentSettingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.PercentSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PercentCurrent
 */
class ReadFanControlPercentCurrent : public ReadAttribute {
public:
    ReadFanControlPercentCurrent()
        : ReadAttribute("percent-current")
    {
    }

    ~ReadFanControlPercentCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributePercentCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.PercentCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl PercentCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlPercentCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlPercentCurrent()
        : SubscribeAttribute("percent-current")
    {
    }

    ~SubscribeAttributeFanControlPercentCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePercentCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.PercentCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SpeedMax
 */
class ReadFanControlSpeedMax : public ReadAttribute {
public:
    ReadFanControlSpeedMax()
        : ReadAttribute("speed-max")
    {
    }

    ~ReadFanControlSpeedMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSpeedMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.SpeedMax response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl SpeedMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlSpeedMax : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlSpeedMax()
        : SubscribeAttribute("speed-max")
    {
    }

    ~SubscribeAttributeFanControlSpeedMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSpeedMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.SpeedMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SpeedSetting
 */
class ReadFanControlSpeedSetting : public ReadAttribute {
public:
    ReadFanControlSpeedSetting()
        : ReadAttribute("speed-setting")
    {
    }

    ~ReadFanControlSpeedSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSpeedSettingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.SpeedSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl SpeedSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlSpeedSetting : public WriteAttribute {
public:
    WriteFanControlSpeedSetting()
        : WriteAttribute("speed-setting")
    {
        AddArgument("attr-name", "speed-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlSpeedSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeSpeedSettingWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("FanControl SpeedSetting write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlSpeedSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlSpeedSetting()
        : SubscribeAttribute("speed-setting")
    {
    }

    ~SubscribeAttributeFanControlSpeedSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSpeedSettingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.SpeedSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SpeedCurrent
 */
class ReadFanControlSpeedCurrent : public ReadAttribute {
public:
    ReadFanControlSpeedCurrent()
        : ReadAttribute("speed-current")
    {
    }

    ~ReadFanControlSpeedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeSpeedCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.SpeedCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl SpeedCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlSpeedCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlSpeedCurrent()
        : SubscribeAttribute("speed-current")
    {
    }

    ~SubscribeAttributeFanControlSpeedCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSpeedCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.SpeedCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RockSupport
 */
class ReadFanControlRockSupport : public ReadAttribute {
public:
    ReadFanControlRockSupport()
        : ReadAttribute("rock-support")
    {
    }

    ~ReadFanControlRockSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeRockSupportWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.RockSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl RockSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlRockSupport : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlRockSupport()
        : SubscribeAttribute("rock-support")
    {
    }

    ~SubscribeAttributeFanControlRockSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRockSupportWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.RockSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RockSetting
 */
class ReadFanControlRockSetting : public ReadAttribute {
public:
    ReadFanControlRockSetting()
        : ReadAttribute("rock-setting")
    {
    }

    ~ReadFanControlRockSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeRockSettingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.RockSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl RockSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlRockSetting : public WriteAttribute {
public:
    WriteFanControlRockSetting()
        : WriteAttribute("rock-setting")
    {
        AddArgument("attr-name", "rock-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlRockSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRockSettingWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("FanControl RockSetting write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlRockSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlRockSetting()
        : SubscribeAttribute("rock-setting")
    {
    }

    ~SubscribeAttributeFanControlRockSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRockSettingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.RockSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WindSupport
 */
class ReadFanControlWindSupport : public ReadAttribute {
public:
    ReadFanControlWindSupport()
        : ReadAttribute("wind-support")
    {
    }

    ~ReadFanControlWindSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeWindSupportWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.WindSupport response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl WindSupport read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlWindSupport : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlWindSupport()
        : SubscribeAttribute("wind-support")
    {
    }

    ~SubscribeAttributeFanControlWindSupport() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWindSupportWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.WindSupport response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WindSetting
 */
class ReadFanControlWindSetting : public ReadAttribute {
public:
    ReadFanControlWindSetting()
        : ReadAttribute("wind-setting")
    {
    }

    ~ReadFanControlWindSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeWindSettingWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.WindSetting response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl WindSetting read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteFanControlWindSetting : public WriteAttribute {
public:
    WriteFanControlWindSetting()
        : WriteAttribute("wind-setting")
    {
        AddArgument("attr-name", "wind-setting");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteFanControlWindSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) WriteAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeWindSettingWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("FanControl WindSetting write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeFanControlWindSetting : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlWindSetting()
        : SubscribeAttribute("wind-setting")
    {
    }

    ~SubscribeAttributeFanControlWindSetting() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWindSettingWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.WindSetting response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadFanControlGeneratedCommandList : public ReadAttribute {
public:
    ReadFanControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadFanControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeFanControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadFanControlAcceptedCommandList : public ReadAttribute {
public:
    ReadFanControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadFanControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeFanControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadFanControlAttributeList : public ReadAttribute {
public:
    ReadFanControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadFanControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeFanControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadFanControlFeatureMap : public ReadAttribute {
public:
    ReadFanControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadFanControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeFanControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadFanControlClusterRevision : public ReadAttribute {
public:
    ReadFanControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadFanControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FanControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("FanControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFanControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeFanControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeFanControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000202) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFanControl * cluster = [[MTRBaseClusterFanControl alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FanControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ThermostatUserInterfaceConfiguration                        | 0x0204 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TemperatureDisplayMode                                            | 0x0000 |
| * KeypadLockout                                                     | 0x0001 |
| * ScheduleProgrammingVisibility                                     | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute TemperatureDisplayMode
 */
class ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode()
        : ReadAttribute("temperature-display-mode")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeTemperatureDisplayModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.TemperatureDisplayMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration TemperatureDisplayMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode : public WriteAttribute {
public:
    WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode()
        : WriteAttribute("temperature-display-mode")
    {
        AddArgument("attr-name", "temperature-display-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeTemperatureDisplayModeWithValue:value
                                                        params:params
                                                    completion:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError("ThermostatUserInterfaceConfiguration "
                                                                       "TemperatureDisplayMode write Error",
                                                                error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode()
        : SubscribeAttribute("temperature-display-mode")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTemperatureDisplayModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.TemperatureDisplayMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute KeypadLockout
 */
class ReadThermostatUserInterfaceConfigurationKeypadLockout : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationKeypadLockout()
        : ReadAttribute("keypad-lockout")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationKeypadLockout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeKeypadLockoutWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.KeypadLockout response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration KeypadLockout read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUserInterfaceConfigurationKeypadLockout : public WriteAttribute {
public:
    WriteThermostatUserInterfaceConfigurationKeypadLockout()
        : WriteAttribute("keypad-lockout")
    {
        AddArgument("attr-name", "keypad-lockout");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUserInterfaceConfigurationKeypadLockout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeKeypadLockoutWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("ThermostatUserInterfaceConfiguration KeypadLockout write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout()
        : SubscribeAttribute("keypad-lockout")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeKeypadLockoutWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.KeypadLockout response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScheduleProgrammingVisibility
 */
class ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility()
        : ReadAttribute("schedule-programming-visibility")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeScheduleProgrammingVisibilityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.ScheduleProgrammingVisibility response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration ScheduleProgrammingVisibility read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility : public WriteAttribute {
public:
    WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility()
        : WriteAttribute("schedule-programming-visibility")
    {
        AddArgument("attr-name", "schedule-programming-visibility");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) WriteAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeScheduleProgrammingVisibilityWithValue:value
                                                               params:params
                                                           completion:^(NSError * _Nullable error) {
                                                               if (error != nil) {
                                                                   LogNSError("ThermostatUserInterfaceConfiguration "
                                                                              "ScheduleProgrammingVisibility write Error",
                                                                       error);
                                                               }
                                                               SetCommandExitStatus(error);
                                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility()
        : SubscribeAttribute("schedule-programming-visibility")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeScheduleProgrammingVisibilityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.ScheduleProgrammingVisibility response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadThermostatUserInterfaceConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadThermostatUserInterfaceConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadThermostatUserInterfaceConfigurationAttributeList : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadThermostatUserInterfaceConfigurationFeatureMap : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadThermostatUserInterfaceConfigurationClusterRevision : public ReadAttribute {
public:
    ReadThermostatUserInterfaceConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadThermostatUserInterfaceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ThermostatUserInterfaceConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ThermostatUserInterfaceConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000204) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterThermostatUserInterfaceConfiguration * cluster =
            [[MTRBaseClusterThermostatUserInterfaceConfiguration alloc] initWithDevice:device
                                                                            endpointID:@(endpointId)
                                                                                 queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ThermostatUserInterfaceConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ColorControl                                                | 0x0300 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * MoveToHue                                                         |   0x00 |
| * MoveHue                                                           |   0x01 |
| * StepHue                                                           |   0x02 |
| * MoveToSaturation                                                  |   0x03 |
| * MoveSaturation                                                    |   0x04 |
| * StepSaturation                                                    |   0x05 |
| * MoveToHueAndSaturation                                            |   0x06 |
| * MoveToColor                                                       |   0x07 |
| * MoveColor                                                         |   0x08 |
| * StepColor                                                         |   0x09 |
| * MoveToColorTemperature                                            |   0x0A |
| * EnhancedMoveToHue                                                 |   0x40 |
| * EnhancedMoveHue                                                   |   0x41 |
| * EnhancedStepHue                                                   |   0x42 |
| * EnhancedMoveToHueAndSaturation                                    |   0x43 |
| * ColorLoopSet                                                      |   0x44 |
| * StopMoveStep                                                      |   0x47 |
| * MoveColorTemperature                                              |   0x4B |
| * StepColorTemperature                                              |   0x4C |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * CurrentHue                                                        | 0x0000 |
| * CurrentSaturation                                                 | 0x0001 |
| * RemainingTime                                                     | 0x0002 |
| * CurrentX                                                          | 0x0003 |
| * CurrentY                                                          | 0x0004 |
| * DriftCompensation                                                 | 0x0005 |
| * CompensationText                                                  | 0x0006 |
| * ColorTemperatureMireds                                            | 0x0007 |
| * ColorMode                                                         | 0x0008 |
| * Options                                                           | 0x000F |
| * NumberOfPrimaries                                                 | 0x0010 |
| * Primary1X                                                         | 0x0011 |
| * Primary1Y                                                         | 0x0012 |
| * Primary1Intensity                                                 | 0x0013 |
| * Primary2X                                                         | 0x0015 |
| * Primary2Y                                                         | 0x0016 |
| * Primary2Intensity                                                 | 0x0017 |
| * Primary3X                                                         | 0x0019 |
| * Primary3Y                                                         | 0x001A |
| * Primary3Intensity                                                 | 0x001B |
| * Primary4X                                                         | 0x0020 |
| * Primary4Y                                                         | 0x0021 |
| * Primary4Intensity                                                 | 0x0022 |
| * Primary5X                                                         | 0x0024 |
| * Primary5Y                                                         | 0x0025 |
| * Primary5Intensity                                                 | 0x0026 |
| * Primary6X                                                         | 0x0028 |
| * Primary6Y                                                         | 0x0029 |
| * Primary6Intensity                                                 | 0x002A |
| * WhitePointX                                                       | 0x0030 |
| * WhitePointY                                                       | 0x0031 |
| * ColorPointRX                                                      | 0x0032 |
| * ColorPointRY                                                      | 0x0033 |
| * ColorPointRIntensity                                              | 0x0034 |
| * ColorPointGX                                                      | 0x0036 |
| * ColorPointGY                                                      | 0x0037 |
| * ColorPointGIntensity                                              | 0x0038 |
| * ColorPointBX                                                      | 0x003A |
| * ColorPointBY                                                      | 0x003B |
| * ColorPointBIntensity                                              | 0x003C |
| * EnhancedCurrentHue                                                | 0x4000 |
| * EnhancedColorMode                                                 | 0x4001 |
| * ColorLoopActive                                                   | 0x4002 |
| * ColorLoopDirection                                                | 0x4003 |
| * ColorLoopTime                                                     | 0x4004 |
| * ColorLoopStartEnhancedHue                                         | 0x4005 |
| * ColorLoopStoredEnhancedHue                                        | 0x4006 |
| * ColorCapabilities                                                 | 0x400A |
| * ColorTempPhysicalMinMireds                                        | 0x400B |
| * ColorTempPhysicalMaxMireds                                        | 0x400C |
| * CoupleColorTempToLevelMinMireds                                   | 0x400D |
| * StartUpColorTemperatureMireds                                     | 0x4010 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command MoveToHue
 */
class ColorControlMoveToHue : public ClusterCommand {
public:
    ColorControlMoveToHue()
        : ClusterCommand("move-to-hue")
    {
        AddArgument("Hue", 0, UINT8_MAX, &mRequest.hue);
        AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveToHueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.hue = [NSNumber numberWithUnsignedChar:mRequest.hue];
        params.direction = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.direction)];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToHueWithParams:params
                              completion:^(NSError * _Nullable error) {
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToHue::Type mRequest;
};

/*
 * Command MoveHue
 */
class ColorControlMoveHue : public ClusterCommand {
public:
    ColorControlMoveHue()
        : ClusterCommand("move-hue")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT8_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveHueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.moveMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.moveMode)];
        params.rate = [NSNumber numberWithUnsignedChar:mRequest.rate];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveHueWithParams:params
                            completion:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveHue::Type mRequest;
};

/*
 * Command StepHue
 */
class ColorControlStepHue : public ClusterCommand {
public:
    ColorControlStepHue()
        : ClusterCommand("step-hue")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT8_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT8_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterStepHueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.stepMode)];
        params.stepSize = [NSNumber numberWithUnsignedChar:mRequest.stepSize];
        params.transitionTime = [NSNumber numberWithUnsignedChar:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stepHueWithParams:params
                            completion:^(NSError * _Nullable error) {
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepHue::Type mRequest;
};

/*
 * Command MoveToSaturation
 */
class ColorControlMoveToSaturation : public ClusterCommand {
public:
    ColorControlMoveToSaturation()
        : ClusterCommand("move-to-saturation")
    {
        AddArgument("Saturation", 0, UINT8_MAX, &mRequest.saturation);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveToSaturationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.saturation = [NSNumber numberWithUnsignedChar:mRequest.saturation];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToSaturationWithParams:params
                                     completion:^(NSError * _Nullable error) {
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToSaturation::Type mRequest;
};

/*
 * Command MoveSaturation
 */
class ColorControlMoveSaturation : public ClusterCommand {
public:
    ColorControlMoveSaturation()
        : ClusterCommand("move-saturation")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT8_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveSaturationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.moveMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.moveMode)];
        params.rate = [NSNumber numberWithUnsignedChar:mRequest.rate];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveSaturationWithParams:params
                                   completion:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveSaturation::Type mRequest;
};

/*
 * Command StepSaturation
 */
class ColorControlStepSaturation : public ClusterCommand {
public:
    ColorControlStepSaturation()
        : ClusterCommand("step-saturation")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT8_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT8_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterStepSaturationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.stepMode)];
        params.stepSize = [NSNumber numberWithUnsignedChar:mRequest.stepSize];
        params.transitionTime = [NSNumber numberWithUnsignedChar:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stepSaturationWithParams:params
                                   completion:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepSaturation::Type mRequest;
};

/*
 * Command MoveToHueAndSaturation
 */
class ColorControlMoveToHueAndSaturation : public ClusterCommand {
public:
    ColorControlMoveToHueAndSaturation()
        : ClusterCommand("move-to-hue-and-saturation")
    {
        AddArgument("Hue", 0, UINT8_MAX, &mRequest.hue);
        AddArgument("Saturation", 0, UINT8_MAX, &mRequest.saturation);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveToHueAndSaturationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.hue = [NSNumber numberWithUnsignedChar:mRequest.hue];
        params.saturation = [NSNumber numberWithUnsignedChar:mRequest.saturation];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToHueAndSaturationWithParams:params
                                           completion:^(NSError * _Nullable error) {
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToHueAndSaturation::Type mRequest;
};

/*
 * Command MoveToColor
 */
class ColorControlMoveToColor : public ClusterCommand {
public:
    ColorControlMoveToColor()
        : ClusterCommand("move-to-color")
    {
        AddArgument("ColorX", 0, UINT16_MAX, &mRequest.colorX);
        AddArgument("ColorY", 0, UINT16_MAX, &mRequest.colorY);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveToColorParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.colorX = [NSNumber numberWithUnsignedShort:mRequest.colorX];
        params.colorY = [NSNumber numberWithUnsignedShort:mRequest.colorY];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToColorWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToColor::Type mRequest;
};

/*
 * Command MoveColor
 */
class ColorControlMoveColor : public ClusterCommand {
public:
    ColorControlMoveColor()
        : ClusterCommand("move-color")
    {
        AddArgument("RateX", INT16_MIN, INT16_MAX, &mRequest.rateX);
        AddArgument("RateY", INT16_MIN, INT16_MAX, &mRequest.rateY);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveColorParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.rateX = [NSNumber numberWithShort:mRequest.rateX];
        params.rateY = [NSNumber numberWithShort:mRequest.rateY];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveColorWithParams:params
                              completion:^(NSError * _Nullable error) {
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveColor::Type mRequest;
};

/*
 * Command StepColor
 */
class ColorControlStepColor : public ClusterCommand {
public:
    ColorControlStepColor()
        : ClusterCommand("step-color")
    {
        AddArgument("StepX", INT16_MIN, INT16_MAX, &mRequest.stepX);
        AddArgument("StepY", INT16_MIN, INT16_MAX, &mRequest.stepY);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterStepColorParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepX = [NSNumber numberWithShort:mRequest.stepX];
        params.stepY = [NSNumber numberWithShort:mRequest.stepY];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stepColorWithParams:params
                              completion:^(NSError * _Nullable error) {
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepColor::Type mRequest;
};

/*
 * Command MoveToColorTemperature
 */
class ColorControlMoveToColorTemperature : public ClusterCommand {
public:
    ColorControlMoveToColorTemperature()
        : ClusterCommand("move-to-color-temperature")
    {
        AddArgument("ColorTemperature", 0, UINT16_MAX, &mRequest.colorTemperature);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveToColorTemperatureParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.colorTemperature = [NSNumber numberWithUnsignedShort:mRequest.colorTemperature];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveToColorTemperatureWithParams:params
                                           completion:^(NSError * _Nullable error) {
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveToColorTemperature::Type mRequest;
};

/*
 * Command EnhancedMoveToHue
 */
class ColorControlEnhancedMoveToHue : public ClusterCommand {
public:
    ColorControlEnhancedMoveToHue()
        : ClusterCommand("enhanced-move-to-hue")
    {
        AddArgument("EnhancedHue", 0, UINT16_MAX, &mRequest.enhancedHue);
        AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000040) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterEnhancedMoveToHueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.enhancedHue = [NSNumber numberWithUnsignedShort:mRequest.enhancedHue];
        params.direction = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.direction)];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enhancedMoveToHueWithParams:params
                                      completion:^(NSError * _Nullable error) {
                                          responsesNeeded--;
                                          if (error != nil) {
                                              mError = error;
                                              LogNSError("Error", error);
                                          }
                                          if (responsesNeeded == 0) {
                                              SetCommandExitStatus(mError);
                                          }
                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedMoveToHue::Type mRequest;
};

/*
 * Command EnhancedMoveHue
 */
class ColorControlEnhancedMoveHue : public ClusterCommand {
public:
    ColorControlEnhancedMoveHue()
        : ClusterCommand("enhanced-move-hue")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT16_MAX, &mRequest.rate);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000041) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterEnhancedMoveHueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.moveMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.moveMode)];
        params.rate = [NSNumber numberWithUnsignedShort:mRequest.rate];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enhancedMoveHueWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedMoveHue::Type mRequest;
};

/*
 * Command EnhancedStepHue
 */
class ColorControlEnhancedStepHue : public ClusterCommand {
public:
    ColorControlEnhancedStepHue()
        : ClusterCommand("enhanced-step-hue")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT16_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000042) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterEnhancedStepHueParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.stepMode)];
        params.stepSize = [NSNumber numberWithUnsignedShort:mRequest.stepSize];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enhancedStepHueWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedStepHue::Type mRequest;
};

/*
 * Command EnhancedMoveToHueAndSaturation
 */
class ColorControlEnhancedMoveToHueAndSaturation : public ClusterCommand {
public:
    ColorControlEnhancedMoveToHueAndSaturation()
        : ClusterCommand("enhanced-move-to-hue-and-saturation")
    {
        AddArgument("EnhancedHue", 0, UINT16_MAX, &mRequest.enhancedHue);
        AddArgument("Saturation", 0, UINT8_MAX, &mRequest.saturation);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000043) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterEnhancedMoveToHueAndSaturationParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.enhancedHue = [NSNumber numberWithUnsignedShort:mRequest.enhancedHue];
        params.saturation = [NSNumber numberWithUnsignedChar:mRequest.saturation];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster enhancedMoveToHueAndSaturationWithParams:params
                                                   completion:^(NSError * _Nullable error) {
                                                       responsesNeeded--;
                                                       if (error != nil) {
                                                           mError = error;
                                                           LogNSError("Error", error);
                                                       }
                                                       if (responsesNeeded == 0) {
                                                           SetCommandExitStatus(mError);
                                                       }
                                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Type mRequest;
};

/*
 * Command ColorLoopSet
 */
class ColorControlColorLoopSet : public ClusterCommand {
public:
    ColorControlColorLoopSet()
        : ClusterCommand("color-loop-set")
    {
        AddArgument("UpdateFlags", 0, UINT8_MAX, &mRequest.updateFlags);
        AddArgument("Action", 0, UINT8_MAX, &mRequest.action);
        AddArgument("Direction", 0, UINT8_MAX, &mRequest.direction);
        AddArgument("Time", 0, UINT16_MAX, &mRequest.time);
        AddArgument("StartHue", 0, UINT16_MAX, &mRequest.startHue);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000044) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterColorLoopSetParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.updateFlags = [NSNumber numberWithUnsignedChar:mRequest.updateFlags.Raw()];
        params.action = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.action)];
        params.direction = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.direction)];
        params.time = [NSNumber numberWithUnsignedShort:mRequest.time];
        params.startHue = [NSNumber numberWithUnsignedShort:mRequest.startHue];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster colorLoopSetWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::ColorLoopSet::Type mRequest;
};

/*
 * Command StopMoveStep
 */
class ColorControlStopMoveStep : public ClusterCommand {
public:
    ColorControlStopMoveStep()
        : ClusterCommand("stop-move-step")
    {
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x00000047) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterStopMoveStepParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopMoveStepWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StopMoveStep::Type mRequest;
};

/*
 * Command MoveColorTemperature
 */
class ColorControlMoveColorTemperature : public ClusterCommand {
public:
    ColorControlMoveColorTemperature()
        : ClusterCommand("move-color-temperature")
    {
        AddArgument("MoveMode", 0, UINT8_MAX, &mRequest.moveMode);
        AddArgument("Rate", 0, UINT16_MAX, &mRequest.rate);
        AddArgument("ColorTemperatureMinimumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMinimumMireds);
        AddArgument("ColorTemperatureMaximumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMaximumMireds);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x0000004B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterMoveColorTemperatureParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.moveMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.moveMode)];
        params.rate = [NSNumber numberWithUnsignedShort:mRequest.rate];
        params.colorTemperatureMinimumMireds = [NSNumber numberWithUnsignedShort:mRequest.colorTemperatureMinimumMireds];
        params.colorTemperatureMaximumMireds = [NSNumber numberWithUnsignedShort:mRequest.colorTemperatureMaximumMireds];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster moveColorTemperatureWithParams:params
                                         completion:^(NSError * _Nullable error) {
                                             responsesNeeded--;
                                             if (error != nil) {
                                                 mError = error;
                                                 LogNSError("Error", error);
                                             }
                                             if (responsesNeeded == 0) {
                                                 SetCommandExitStatus(mError);
                                             }
                                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::MoveColorTemperature::Type mRequest;
};

/*
 * Command StepColorTemperature
 */
class ColorControlStepColorTemperature : public ClusterCommand {
public:
    ColorControlStepColorTemperature()
        : ClusterCommand("step-color-temperature")
    {
        AddArgument("StepMode", 0, UINT8_MAX, &mRequest.stepMode);
        AddArgument("StepSize", 0, UINT16_MAX, &mRequest.stepSize);
        AddArgument("TransitionTime", 0, UINT16_MAX, &mRequest.transitionTime);
        AddArgument("ColorTemperatureMinimumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMinimumMireds);
        AddArgument("ColorTemperatureMaximumMireds", 0, UINT16_MAX, &mRequest.colorTemperatureMaximumMireds);
        AddArgument("OptionsMask", 0, UINT8_MAX, &mRequest.optionsMask);
        AddArgument("OptionsOverride", 0, UINT8_MAX, &mRequest.optionsOverride);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) command (0x0000004C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRColorControlClusterStepColorTemperatureParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.stepMode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.stepMode)];
        params.stepSize = [NSNumber numberWithUnsignedShort:mRequest.stepSize];
        params.transitionTime = [NSNumber numberWithUnsignedShort:mRequest.transitionTime];
        params.colorTemperatureMinimumMireds = [NSNumber numberWithUnsignedShort:mRequest.colorTemperatureMinimumMireds];
        params.colorTemperatureMaximumMireds = [NSNumber numberWithUnsignedShort:mRequest.colorTemperatureMaximumMireds];
        params.optionsMask = [NSNumber numberWithUnsignedChar:mRequest.optionsMask];
        params.optionsOverride = [NSNumber numberWithUnsignedChar:mRequest.optionsOverride];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stepColorTemperatureWithParams:params
                                         completion:^(NSError * _Nullable error) {
                                             responsesNeeded--;
                                             if (error != nil) {
                                                 mError = error;
                                                 LogNSError("Error", error);
                                             }
                                             if (responsesNeeded == 0) {
                                                 SetCommandExitStatus(mError);
                                             }
                                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ColorControl::Commands::StepColorTemperature::Type mRequest;
};

/*
 * Attribute CurrentHue
 */
class ReadColorControlCurrentHue : public ReadAttribute {
public:
    ReadColorControlCurrentHue()
        : ReadAttribute("current-hue")
    {
    }

    ~ReadColorControlCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentHueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentHue response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentHue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentHue()
        : SubscribeAttribute("current-hue")
    {
    }

    ~SubscribeAttributeColorControlCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentHueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentSaturation
 */
class ReadColorControlCurrentSaturation : public ReadAttribute {
public:
    ReadColorControlCurrentSaturation()
        : ReadAttribute("current-saturation")
    {
    }

    ~ReadColorControlCurrentSaturation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentSaturationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentSaturation response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentSaturation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentSaturation : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentSaturation()
        : SubscribeAttribute("current-saturation")
    {
    }

    ~SubscribeAttributeColorControlCurrentSaturation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentSaturationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentSaturation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RemainingTime
 */
class ReadColorControlRemainingTime : public ReadAttribute {
public:
    ReadColorControlRemainingTime()
        : ReadAttribute("remaining-time")
    {
    }

    ~ReadColorControlRemainingTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeRemainingTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.RemainingTime response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl RemainingTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlRemainingTime : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlRemainingTime()
        : SubscribeAttribute("remaining-time")
    {
    }

    ~SubscribeAttributeColorControlRemainingTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRemainingTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.RemainingTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentX
 */
class ReadColorControlCurrentX : public ReadAttribute {
public:
    ReadColorControlCurrentX()
        : ReadAttribute("current-x")
    {
    }

    ~ReadColorControlCurrentX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentXWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentX()
        : SubscribeAttribute("current-x")
    {
    }

    ~SubscribeAttributeColorControlCurrentX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentXWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentY
 */
class ReadColorControlCurrentY : public ReadAttribute {
public:
    ReadColorControlCurrentY()
        : ReadAttribute("current-y")
    {
    }

    ~ReadColorControlCurrentY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCurrentYWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CurrentY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CurrentY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCurrentY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCurrentY()
        : SubscribeAttribute("current-y")
    {
    }

    ~SubscribeAttributeColorControlCurrentY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentYWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CurrentY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DriftCompensation
 */
class ReadColorControlDriftCompensation : public ReadAttribute {
public:
    ReadColorControlDriftCompensation()
        : ReadAttribute("drift-compensation")
    {
    }

    ~ReadColorControlDriftCompensation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeDriftCompensationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.DriftCompensation response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl DriftCompensation read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlDriftCompensation : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlDriftCompensation()
        : SubscribeAttribute("drift-compensation")
    {
    }

    ~SubscribeAttributeColorControlDriftCompensation() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDriftCompensationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.DriftCompensation response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CompensationText
 */
class ReadColorControlCompensationText : public ReadAttribute {
public:
    ReadColorControlCompensationText()
        : ReadAttribute("compensation-text")
    {
    }

    ~ReadColorControlCompensationText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeCompensationTextWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.CompensationText response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl CompensationText read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCompensationText : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCompensationText()
        : SubscribeAttribute("compensation-text")
    {
    }

    ~SubscribeAttributeColorControlCompensationText() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCompensationTextWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CompensationText response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorTemperatureMireds
 */
class ReadColorControlColorTemperatureMireds : public ReadAttribute {
public:
    ReadColorControlColorTemperatureMireds()
        : ReadAttribute("color-temperature-mireds")
    {
    }

    ~ReadColorControlColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorTemperatureMiredsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorTemperatureMireds response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorTemperatureMireds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorTemperatureMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorTemperatureMireds()
        : SubscribeAttribute("color-temperature-mireds")
    {
    }

    ~SubscribeAttributeColorControlColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorTemperatureMiredsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTemperatureMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorMode
 */
class ReadColorControlColorMode : public ReadAttribute {
public:
    ReadColorControlColorMode()
        : ReadAttribute("color-mode")
    {
    }

    ~ReadColorControlColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorMode : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorMode()
        : SubscribeAttribute("color-mode")
    {
    }

    ~SubscribeAttributeColorControlColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Options
 */
class ReadColorControlOptions : public ReadAttribute {
public:
    ReadColorControlOptions()
        : ReadAttribute("options")
    {
    }

    ~ReadColorControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeOptionsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Options response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Options read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlOptions : public WriteAttribute {
public:
    WriteColorControlOptions()
        : WriteAttribute("options")
    {
        AddArgument("attr-name", "options");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOptionsWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("ColorControl Options write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlOptions : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlOptions()
        : SubscribeAttribute("options")
    {
    }

    ~SubscribeAttributeColorControlOptions() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOptionsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Options response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NumberOfPrimaries
 */
class ReadColorControlNumberOfPrimaries : public ReadAttribute {
public:
    ReadColorControlNumberOfPrimaries()
        : ReadAttribute("number-of-primaries")
    {
    }

    ~ReadColorControlNumberOfPrimaries() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeNumberOfPrimariesWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.NumberOfPrimaries response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl NumberOfPrimaries read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlNumberOfPrimaries : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlNumberOfPrimaries()
        : SubscribeAttribute("number-of-primaries")
    {
    }

    ~SubscribeAttributeColorControlNumberOfPrimaries() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNumberOfPrimariesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.NumberOfPrimaries response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary1X
 */
class ReadColorControlPrimary1X : public ReadAttribute {
public:
    ReadColorControlPrimary1X()
        : ReadAttribute("primary1x")
    {
    }

    ~ReadColorControlPrimary1X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary1XWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary1X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary1X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary1X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary1X()
        : SubscribeAttribute("primary1x")
    {
    }

    ~SubscribeAttributeColorControlPrimary1X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary1XWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary1X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary1Y
 */
class ReadColorControlPrimary1Y : public ReadAttribute {
public:
    ReadColorControlPrimary1Y()
        : ReadAttribute("primary1y")
    {
    }

    ~ReadColorControlPrimary1Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary1YWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary1Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary1Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary1Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary1Y()
        : SubscribeAttribute("primary1y")
    {
    }

    ~SubscribeAttributeColorControlPrimary1Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary1YWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary1Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary1Intensity
 */
class ReadColorControlPrimary1Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary1Intensity()
        : ReadAttribute("primary1intensity")
    {
    }

    ~ReadColorControlPrimary1Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary1IntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary1Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary1Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary1Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary1Intensity()
        : SubscribeAttribute("primary1intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary1Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary1IntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary1Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary2X
 */
class ReadColorControlPrimary2X : public ReadAttribute {
public:
    ReadColorControlPrimary2X()
        : ReadAttribute("primary2x")
    {
    }

    ~ReadColorControlPrimary2X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary2XWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary2X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary2X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary2X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary2X()
        : SubscribeAttribute("primary2x")
    {
    }

    ~SubscribeAttributeColorControlPrimary2X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary2XWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary2X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary2Y
 */
class ReadColorControlPrimary2Y : public ReadAttribute {
public:
    ReadColorControlPrimary2Y()
        : ReadAttribute("primary2y")
    {
    }

    ~ReadColorControlPrimary2Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary2YWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary2Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary2Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary2Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary2Y()
        : SubscribeAttribute("primary2y")
    {
    }

    ~SubscribeAttributeColorControlPrimary2Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary2YWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary2Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary2Intensity
 */
class ReadColorControlPrimary2Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary2Intensity()
        : ReadAttribute("primary2intensity")
    {
    }

    ~ReadColorControlPrimary2Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary2IntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary2Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary2Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary2Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary2Intensity()
        : SubscribeAttribute("primary2intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary2Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary2IntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary2Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary3X
 */
class ReadColorControlPrimary3X : public ReadAttribute {
public:
    ReadColorControlPrimary3X()
        : ReadAttribute("primary3x")
    {
    }

    ~ReadColorControlPrimary3X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary3XWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary3X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary3X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary3X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary3X()
        : SubscribeAttribute("primary3x")
    {
    }

    ~SubscribeAttributeColorControlPrimary3X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary3XWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary3X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary3Y
 */
class ReadColorControlPrimary3Y : public ReadAttribute {
public:
    ReadColorControlPrimary3Y()
        : ReadAttribute("primary3y")
    {
    }

    ~ReadColorControlPrimary3Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary3YWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary3Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary3Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary3Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary3Y()
        : SubscribeAttribute("primary3y")
    {
    }

    ~SubscribeAttributeColorControlPrimary3Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary3YWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary3Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary3Intensity
 */
class ReadColorControlPrimary3Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary3Intensity()
        : ReadAttribute("primary3intensity")
    {
    }

    ~ReadColorControlPrimary3Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary3IntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary3Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary3Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary3Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary3Intensity()
        : SubscribeAttribute("primary3intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary3Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary3IntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary3Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary4X
 */
class ReadColorControlPrimary4X : public ReadAttribute {
public:
    ReadColorControlPrimary4X()
        : ReadAttribute("primary4x")
    {
    }

    ~ReadColorControlPrimary4X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary4XWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary4X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary4X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary4X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary4X()
        : SubscribeAttribute("primary4x")
    {
    }

    ~SubscribeAttributeColorControlPrimary4X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary4XWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary4X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary4Y
 */
class ReadColorControlPrimary4Y : public ReadAttribute {
public:
    ReadColorControlPrimary4Y()
        : ReadAttribute("primary4y")
    {
    }

    ~ReadColorControlPrimary4Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary4YWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary4Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary4Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary4Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary4Y()
        : SubscribeAttribute("primary4y")
    {
    }

    ~SubscribeAttributeColorControlPrimary4Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary4YWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary4Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary4Intensity
 */
class ReadColorControlPrimary4Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary4Intensity()
        : ReadAttribute("primary4intensity")
    {
    }

    ~ReadColorControlPrimary4Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary4IntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary4Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary4Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary4Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary4Intensity()
        : SubscribeAttribute("primary4intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary4Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary4IntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary4Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary5X
 */
class ReadColorControlPrimary5X : public ReadAttribute {
public:
    ReadColorControlPrimary5X()
        : ReadAttribute("primary5x")
    {
    }

    ~ReadColorControlPrimary5X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary5XWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary5X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary5X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary5X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary5X()
        : SubscribeAttribute("primary5x")
    {
    }

    ~SubscribeAttributeColorControlPrimary5X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary5XWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary5X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary5Y
 */
class ReadColorControlPrimary5Y : public ReadAttribute {
public:
    ReadColorControlPrimary5Y()
        : ReadAttribute("primary5y")
    {
    }

    ~ReadColorControlPrimary5Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary5YWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary5Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary5Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary5Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary5Y()
        : SubscribeAttribute("primary5y")
    {
    }

    ~SubscribeAttributeColorControlPrimary5Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary5YWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary5Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary5Intensity
 */
class ReadColorControlPrimary5Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary5Intensity()
        : ReadAttribute("primary5intensity")
    {
    }

    ~ReadColorControlPrimary5Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary5IntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary5Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary5Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary5Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary5Intensity()
        : SubscribeAttribute("primary5intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary5Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary5IntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary5Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary6X
 */
class ReadColorControlPrimary6X : public ReadAttribute {
public:
    ReadColorControlPrimary6X()
        : ReadAttribute("primary6x")
    {
    }

    ~ReadColorControlPrimary6X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary6XWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary6X response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary6X read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary6X : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary6X()
        : SubscribeAttribute("primary6x")
    {
    }

    ~SubscribeAttributeColorControlPrimary6X() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary6XWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary6X response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary6Y
 */
class ReadColorControlPrimary6Y : public ReadAttribute {
public:
    ReadColorControlPrimary6Y()
        : ReadAttribute("primary6y")
    {
    }

    ~ReadColorControlPrimary6Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary6YWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary6Y response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary6Y read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary6Y : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary6Y()
        : SubscribeAttribute("primary6y")
    {
    }

    ~SubscribeAttributeColorControlPrimary6Y() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary6YWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary6Y response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Primary6Intensity
 */
class ReadColorControlPrimary6Intensity : public ReadAttribute {
public:
    ReadColorControlPrimary6Intensity()
        : ReadAttribute("primary6intensity")
    {
    }

    ~ReadColorControlPrimary6Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributePrimary6IntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.Primary6Intensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl Primary6Intensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlPrimary6Intensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlPrimary6Intensity()
        : SubscribeAttribute("primary6intensity")
    {
    }

    ~SubscribeAttributeColorControlPrimary6Intensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePrimary6IntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.Primary6Intensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WhitePointX
 */
class ReadColorControlWhitePointX : public ReadAttribute {
public:
    ReadColorControlWhitePointX()
        : ReadAttribute("white-point-x")
    {
    }

    ~ReadColorControlWhitePointX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeWhitePointXWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.WhitePointX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl WhitePointX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlWhitePointX : public WriteAttribute {
public:
    WriteColorControlWhitePointX()
        : WriteAttribute("white-point-x")
    {
        AddArgument("attr-name", "white-point-x");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlWhitePointX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeWhitePointXWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("ColorControl WhitePointX write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlWhitePointX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlWhitePointX()
        : SubscribeAttribute("white-point-x")
    {
    }

    ~SubscribeAttributeColorControlWhitePointX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWhitePointXWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.WhitePointX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WhitePointY
 */
class ReadColorControlWhitePointY : public ReadAttribute {
public:
    ReadColorControlWhitePointY()
        : ReadAttribute("white-point-y")
    {
    }

    ~ReadColorControlWhitePointY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeWhitePointYWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.WhitePointY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl WhitePointY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlWhitePointY : public WriteAttribute {
public:
    WriteColorControlWhitePointY()
        : WriteAttribute("white-point-y")
    {
        AddArgument("attr-name", "white-point-y");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlWhitePointY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeWhitePointYWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("ColorControl WhitePointY write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlWhitePointY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlWhitePointY()
        : SubscribeAttribute("white-point-y")
    {
    }

    ~SubscribeAttributeColorControlWhitePointY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWhitePointYWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.WhitePointY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointRX
 */
class ReadColorControlColorPointRX : public ReadAttribute {
public:
    ReadColorControlColorPointRX()
        : ReadAttribute("color-point-rx")
    {
    }

    ~ReadColorControlColorPointRX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointRXWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointRX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointRX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointRX : public WriteAttribute {
public:
    WriteColorControlColorPointRX()
        : WriteAttribute("color-point-rx")
    {
        AddArgument("attr-name", "color-point-rx");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointRX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointRXWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ColorControl ColorPointRX write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointRX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointRX()
        : SubscribeAttribute("color-point-rx")
    {
    }

    ~SubscribeAttributeColorControlColorPointRX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointRXWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointRX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointRY
 */
class ReadColorControlColorPointRY : public ReadAttribute {
public:
    ReadColorControlColorPointRY()
        : ReadAttribute("color-point-ry")
    {
    }

    ~ReadColorControlColorPointRY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointRYWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointRY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointRY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointRY : public WriteAttribute {
public:
    WriteColorControlColorPointRY()
        : WriteAttribute("color-point-ry")
    {
        AddArgument("attr-name", "color-point-ry");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointRY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointRYWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ColorControl ColorPointRY write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointRY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointRY()
        : SubscribeAttribute("color-point-ry")
    {
    }

    ~SubscribeAttributeColorControlColorPointRY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointRYWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointRY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointRIntensity
 */
class ReadColorControlColorPointRIntensity : public ReadAttribute {
public:
    ReadColorControlColorPointRIntensity()
        : ReadAttribute("color-point-rintensity")
    {
    }

    ~ReadColorControlColorPointRIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointRIntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointRIntensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointRIntensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointRIntensity : public WriteAttribute {
public:
    WriteColorControlColorPointRIntensity()
        : WriteAttribute("color-point-rintensity")
    {
        AddArgument("attr-name", "color-point-rintensity");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointRIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeColorPointRIntensityWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("ColorControl ColorPointRIntensity write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlColorPointRIntensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointRIntensity()
        : SubscribeAttribute("color-point-rintensity")
    {
    }

    ~SubscribeAttributeColorControlColorPointRIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointRIntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointRIntensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointGX
 */
class ReadColorControlColorPointGX : public ReadAttribute {
public:
    ReadColorControlColorPointGX()
        : ReadAttribute("color-point-gx")
    {
    }

    ~ReadColorControlColorPointGX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000036) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointGXWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointGX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointGX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointGX : public WriteAttribute {
public:
    WriteColorControlColorPointGX()
        : WriteAttribute("color-point-gx")
    {
        AddArgument("attr-name", "color-point-gx");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointGX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointGXWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ColorControl ColorPointGX write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointGX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointGX()
        : SubscribeAttribute("color-point-gx")
    {
    }

    ~SubscribeAttributeColorControlColorPointGX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000036) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointGXWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointGX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointGY
 */
class ReadColorControlColorPointGY : public ReadAttribute {
public:
    ReadColorControlColorPointGY()
        : ReadAttribute("color-point-gy")
    {
    }

    ~ReadColorControlColorPointGY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000037) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointGYWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointGY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointGY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointGY : public WriteAttribute {
public:
    WriteColorControlColorPointGY()
        : WriteAttribute("color-point-gy")
    {
        AddArgument("attr-name", "color-point-gy");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointGY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointGYWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ColorControl ColorPointGY write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointGY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointGY()
        : SubscribeAttribute("color-point-gy")
    {
    }

    ~SubscribeAttributeColorControlColorPointGY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000037) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointGYWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointGY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointGIntensity
 */
class ReadColorControlColorPointGIntensity : public ReadAttribute {
public:
    ReadColorControlColorPointGIntensity()
        : ReadAttribute("color-point-gintensity")
    {
    }

    ~ReadColorControlColorPointGIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00000038) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointGIntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointGIntensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointGIntensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointGIntensity : public WriteAttribute {
public:
    WriteColorControlColorPointGIntensity()
        : WriteAttribute("color-point-gintensity")
    {
        AddArgument("attr-name", "color-point-gintensity");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointGIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeColorPointGIntensityWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("ColorControl ColorPointGIntensity write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlColorPointGIntensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointGIntensity()
        : SubscribeAttribute("color-point-gintensity")
    {
    }

    ~SubscribeAttributeColorControlColorPointGIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00000038) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointGIntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointGIntensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointBX
 */
class ReadColorControlColorPointBX : public ReadAttribute {
public:
    ReadColorControlColorPointBX()
        : ReadAttribute("color-point-bx")
    {
    }

    ~ReadColorControlColorPointBX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000003A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointBXWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointBX response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointBX read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointBX : public WriteAttribute {
public:
    WriteColorControlColorPointBX()
        : WriteAttribute("color-point-bx")
    {
        AddArgument("attr-name", "color-point-bx");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointBX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointBXWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ColorControl ColorPointBX write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointBX : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointBX()
        : SubscribeAttribute("color-point-bx")
    {
    }

    ~SubscribeAttributeColorControlColorPointBX() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000003A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointBXWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointBX response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointBY
 */
class ReadColorControlColorPointBY : public ReadAttribute {
public:
    ReadColorControlColorPointBY()
        : ReadAttribute("color-point-by")
    {
    }

    ~ReadColorControlColorPointBY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000003B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointBYWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointBY response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointBY read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointBY : public WriteAttribute {
public:
    WriteColorControlColorPointBY()
        : WriteAttribute("color-point-by")
    {
        AddArgument("attr-name", "color-point-by");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointBY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000003B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeColorPointBYWithValue:value
                                              params:params
                                          completion:^(NSError * _Nullable error) {
                                              if (error != nil) {
                                                  LogNSError("ColorControl ColorPointBY write Error", error);
                                              }
                                              SetCommandExitStatus(error);
                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlColorPointBY : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointBY()
        : SubscribeAttribute("color-point-by")
    {
    }

    ~SubscribeAttributeColorControlColorPointBY() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000003B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointBYWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointBY response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorPointBIntensity
 */
class ReadColorControlColorPointBIntensity : public ReadAttribute {
public:
    ReadColorControlColorPointBIntensity()
        : ReadAttribute("color-point-bintensity")
    {
    }

    ~ReadColorControlColorPointBIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000003C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorPointBIntensityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorPointBIntensity response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorPointBIntensity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlColorPointBIntensity : public WriteAttribute {
public:
    WriteColorControlColorPointBIntensity()
        : WriteAttribute("color-point-bintensity")
    {
        AddArgument("attr-name", "color-point-bintensity");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlColorPointBIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x0000003C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeColorPointBIntensityWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("ColorControl ColorPointBIntensity write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeColorControlColorPointBIntensity : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorPointBIntensity()
        : SubscribeAttribute("color-point-bintensity")
    {
    }

    ~SubscribeAttributeColorControlColorPointBIntensity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000003C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorPointBIntensityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorPointBIntensity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnhancedCurrentHue
 */
class ReadColorControlEnhancedCurrentHue : public ReadAttribute {
public:
    ReadColorControlEnhancedCurrentHue()
        : ReadAttribute("enhanced-current-hue")
    {
    }

    ~ReadColorControlEnhancedCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeEnhancedCurrentHueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.EnhancedCurrentHue response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl EnhancedCurrentHue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlEnhancedCurrentHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlEnhancedCurrentHue()
        : SubscribeAttribute("enhanced-current-hue")
    {
    }

    ~SubscribeAttributeColorControlEnhancedCurrentHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnhancedCurrentHueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.EnhancedCurrentHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnhancedColorMode
 */
class ReadColorControlEnhancedColorMode : public ReadAttribute {
public:
    ReadColorControlEnhancedColorMode()
        : ReadAttribute("enhanced-color-mode")
    {
    }

    ~ReadColorControlEnhancedColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeEnhancedColorModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.EnhancedColorMode response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl EnhancedColorMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlEnhancedColorMode : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlEnhancedColorMode()
        : SubscribeAttribute("enhanced-color-mode")
    {
    }

    ~SubscribeAttributeColorControlEnhancedColorMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnhancedColorModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.EnhancedColorMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopActive
 */
class ReadColorControlColorLoopActive : public ReadAttribute {
public:
    ReadColorControlColorLoopActive()
        : ReadAttribute("color-loop-active")
    {
    }

    ~ReadColorControlColorLoopActive() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopActiveWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopActive response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopActive read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopActive : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopActive()
        : SubscribeAttribute("color-loop-active")
    {
    }

    ~SubscribeAttributeColorControlColorLoopActive() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorLoopActiveWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopActive response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopDirection
 */
class ReadColorControlColorLoopDirection : public ReadAttribute {
public:
    ReadColorControlColorLoopDirection()
        : ReadAttribute("color-loop-direction")
    {
    }

    ~ReadColorControlColorLoopDirection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopDirectionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopDirection response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopDirection read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopDirection : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopDirection()
        : SubscribeAttribute("color-loop-direction")
    {
    }

    ~SubscribeAttributeColorControlColorLoopDirection() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorLoopDirectionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopDirection response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopTime
 */
class ReadColorControlColorLoopTime : public ReadAttribute {
public:
    ReadColorControlColorLoopTime()
        : ReadAttribute("color-loop-time")
    {
    }

    ~ReadColorControlColorLoopTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopTime response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopTime : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopTime()
        : SubscribeAttribute("color-loop-time")
    {
    }

    ~SubscribeAttributeColorControlColorLoopTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorLoopTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopStartEnhancedHue
 */
class ReadColorControlColorLoopStartEnhancedHue : public ReadAttribute {
public:
    ReadColorControlColorLoopStartEnhancedHue()
        : ReadAttribute("color-loop-start-enhanced-hue")
    {
    }

    ~ReadColorControlColorLoopStartEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopStartEnhancedHueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopStartEnhancedHue response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopStartEnhancedHue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopStartEnhancedHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopStartEnhancedHue()
        : SubscribeAttribute("color-loop-start-enhanced-hue")
    {
    }

    ~SubscribeAttributeColorControlColorLoopStartEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorLoopStartEnhancedHueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopStartEnhancedHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorLoopStoredEnhancedHue
 */
class ReadColorControlColorLoopStoredEnhancedHue : public ReadAttribute {
public:
    ReadColorControlColorLoopStoredEnhancedHue()
        : ReadAttribute("color-loop-stored-enhanced-hue")
    {
    }

    ~ReadColorControlColorLoopStoredEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorLoopStoredEnhancedHueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorLoopStoredEnhancedHue response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorLoopStoredEnhancedHue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorLoopStoredEnhancedHue : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorLoopStoredEnhancedHue()
        : SubscribeAttribute("color-loop-stored-enhanced-hue")
    {
    }

    ~SubscribeAttributeColorControlColorLoopStoredEnhancedHue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorLoopStoredEnhancedHueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorLoopStoredEnhancedHue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorCapabilities
 */
class ReadColorControlColorCapabilities : public ReadAttribute {
public:
    ReadColorControlColorCapabilities()
        : ReadAttribute("color-capabilities")
    {
    }

    ~ReadColorControlColorCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorCapabilitiesWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorCapabilities response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorCapabilities read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorCapabilities : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorCapabilities()
        : SubscribeAttribute("color-capabilities")
    {
    }

    ~SubscribeAttributeColorControlColorCapabilities() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorCapabilitiesWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorCapabilities response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorTempPhysicalMinMireds
 */
class ReadColorControlColorTempPhysicalMinMireds : public ReadAttribute {
public:
    ReadColorControlColorTempPhysicalMinMireds()
        : ReadAttribute("color-temp-physical-min-mireds")
    {
    }

    ~ReadColorControlColorTempPhysicalMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorTempPhysicalMinMiredsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorTempPhysicalMinMireds response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorTempPhysicalMinMireds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorTempPhysicalMinMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorTempPhysicalMinMireds()
        : SubscribeAttribute("color-temp-physical-min-mireds")
    {
    }

    ~SubscribeAttributeColorControlColorTempPhysicalMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorTempPhysicalMinMiredsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTempPhysicalMinMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ColorTempPhysicalMaxMireds
 */
class ReadColorControlColorTempPhysicalMaxMireds : public ReadAttribute {
public:
    ReadColorControlColorTempPhysicalMaxMireds()
        : ReadAttribute("color-temp-physical-max-mireds")
    {
    }

    ~ReadColorControlColorTempPhysicalMaxMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeColorTempPhysicalMaxMiredsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ColorTempPhysicalMaxMireds response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ColorTempPhysicalMaxMireds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlColorTempPhysicalMaxMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlColorTempPhysicalMaxMireds()
        : SubscribeAttribute("color-temp-physical-max-mireds")
    {
    }

    ~SubscribeAttributeColorControlColorTempPhysicalMaxMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeColorTempPhysicalMaxMiredsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ColorTempPhysicalMaxMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CoupleColorTempToLevelMinMireds
 */
class ReadColorControlCoupleColorTempToLevelMinMireds : public ReadAttribute {
public:
    ReadColorControlCoupleColorTempToLevelMinMireds()
        : ReadAttribute("couple-color-temp-to-level-min-mireds")
    {
    }

    ~ReadColorControlCoupleColorTempToLevelMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000400D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster
            readAttributeCoupleColorTempToLevelMinMiredsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CoupleColorTempToLevelMinMireds response %@", [value description]);
                if (error != nil) {
                    LogNSError("ColorControl CoupleColorTempToLevelMinMireds read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds()
        : SubscribeAttribute("couple-color-temp-to-level-min-mireds")
    {
    }

    ~SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000400D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCoupleColorTempToLevelMinMiredsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.CoupleColorTempToLevelMinMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartUpColorTemperatureMireds
 */
class ReadColorControlStartUpColorTemperatureMireds : public ReadAttribute {
public:
    ReadColorControlStartUpColorTemperatureMireds()
        : ReadAttribute("start-up-color-temperature-mireds")
    {
    }

    ~ReadColorControlStartUpColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x00004010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeStartUpColorTemperatureMiredsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.StartUpColorTemperatureMireds response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl StartUpColorTemperatureMireds read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteColorControlStartUpColorTemperatureMireds : public WriteAttribute {
public:
    WriteColorControlStartUpColorTemperatureMireds()
        : WriteAttribute("start-up-color-temperature-mireds")
    {
        AddArgument("attr-name", "start-up-color-temperature-mireds");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteColorControlStartUpColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) WriteAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeStartUpColorTemperatureMiredsWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "ColorControl StartUpColorTemperatureMireds write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeColorControlStartUpColorTemperatureMireds : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlStartUpColorTemperatureMireds()
        : SubscribeAttribute("start-up-color-temperature-mireds")
    {
    }

    ~SubscribeAttributeColorControlStartUpColorTemperatureMireds() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStartUpColorTemperatureMiredsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.StartUpColorTemperatureMireds response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadColorControlGeneratedCommandList : public ReadAttribute {
public:
    ReadColorControlGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadColorControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeColorControlGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadColorControlAcceptedCommandList : public ReadAttribute {
public:
    ReadColorControlAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadColorControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeColorControlAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadColorControlAttributeList : public ReadAttribute {
public:
    ReadColorControlAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadColorControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeColorControlAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadColorControlFeatureMap : public ReadAttribute {
public:
    ReadColorControlFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadColorControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeColorControlFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadColorControlClusterRevision : public ReadAttribute {
public:
    ReadColorControlClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadColorControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ColorControl.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ColorControl ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeColorControlClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeColorControlClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeColorControlClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000300) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterColorControl * cluster = [[MTRBaseClusterColorControl alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ColorControl.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster BallastConfiguration                                        | 0x0301 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * PhysicalMinLevel                                                  | 0x0000 |
| * PhysicalMaxLevel                                                  | 0x0001 |
| * BallastStatus                                                     | 0x0002 |
| * MinLevel                                                          | 0x0010 |
| * MaxLevel                                                          | 0x0011 |
| * IntrinsicBalanceFactor                                            | 0x0014 |
| * BallastFactorAdjustment                                           | 0x0015 |
| * LampQuantity                                                      | 0x0020 |
| * LampType                                                          | 0x0030 |
| * LampManufacturer                                                  | 0x0031 |
| * LampRatedHours                                                    | 0x0032 |
| * LampBurnHours                                                     | 0x0033 |
| * LampAlarmMode                                                     | 0x0034 |
| * LampBurnHoursTripPoint                                            | 0x0035 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute PhysicalMinLevel
 */
class ReadBallastConfigurationPhysicalMinLevel : public ReadAttribute {
public:
    ReadBallastConfigurationPhysicalMinLevel()
        : ReadAttribute("physical-min-level")
    {
    }

    ~ReadBallastConfigurationPhysicalMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributePhysicalMinLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.PhysicalMinLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration PhysicalMinLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationPhysicalMinLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationPhysicalMinLevel()
        : SubscribeAttribute("physical-min-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationPhysicalMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalMinLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.PhysicalMinLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalMaxLevel
 */
class ReadBallastConfigurationPhysicalMaxLevel : public ReadAttribute {
public:
    ReadBallastConfigurationPhysicalMaxLevel()
        : ReadAttribute("physical-max-level")
    {
    }

    ~ReadBallastConfigurationPhysicalMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributePhysicalMaxLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.PhysicalMaxLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration PhysicalMaxLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationPhysicalMaxLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationPhysicalMaxLevel()
        : SubscribeAttribute("physical-max-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationPhysicalMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalMaxLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.PhysicalMaxLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BallastStatus
 */
class ReadBallastConfigurationBallastStatus : public ReadAttribute {
public:
    ReadBallastConfigurationBallastStatus()
        : ReadAttribute("ballast-status")
    {
    }

    ~ReadBallastConfigurationBallastStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBallastStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.BallastStatus response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration BallastStatus read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationBallastStatus : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationBallastStatus()
        : SubscribeAttribute("ballast-status")
    {
    }

    ~SubscribeAttributeBallastConfigurationBallastStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBallastStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.BallastStatus response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinLevel
 */
class ReadBallastConfigurationMinLevel : public ReadAttribute {
public:
    ReadBallastConfigurationMinLevel()
        : ReadAttribute("min-level")
    {
    }

    ~ReadBallastConfigurationMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeMinLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.MinLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration MinLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationMinLevel : public WriteAttribute {
public:
    WriteBallastConfigurationMinLevel()
        : WriteAttribute("min-level")
    {
        AddArgument("attr-name", "min-level");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeMinLevelWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("BallastConfiguration MinLevel write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationMinLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationMinLevel()
        : SubscribeAttribute("min-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationMinLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.MinLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxLevel
 */
class ReadBallastConfigurationMaxLevel : public ReadAttribute {
public:
    ReadBallastConfigurationMaxLevel()
        : ReadAttribute("max-level")
    {
    }

    ~ReadBallastConfigurationMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeMaxLevelWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.MaxLevel response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration MaxLevel read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationMaxLevel : public WriteAttribute {
public:
    WriteBallastConfigurationMaxLevel()
        : WriteAttribute("max-level")
    {
        AddArgument("attr-name", "max-level");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeMaxLevelWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("BallastConfiguration MaxLevel write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationMaxLevel : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationMaxLevel()
        : SubscribeAttribute("max-level")
    {
    }

    ~SubscribeAttributeBallastConfigurationMaxLevel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxLevelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.MaxLevel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute IntrinsicBalanceFactor
 */
class ReadBallastConfigurationIntrinsicBalanceFactor : public ReadAttribute {
public:
    ReadBallastConfigurationIntrinsicBalanceFactor()
        : ReadAttribute("intrinsic-balance-factor")
    {
    }

    ~ReadBallastConfigurationIntrinsicBalanceFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeIntrinsicBalanceFactorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.IntrinsicBalanceFactor response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration IntrinsicBalanceFactor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationIntrinsicBalanceFactor : public WriteAttribute {
public:
    WriteBallastConfigurationIntrinsicBalanceFactor()
        : WriteAttribute("intrinsic-balance-factor")
    {
        AddArgument("attr-name", "intrinsic-balance-factor");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationIntrinsicBalanceFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeIntrinsicBalanceFactorWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("BallastConfiguration IntrinsicBalanceFactor write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor()
        : SubscribeAttribute("intrinsic-balance-factor")
    {
    }

    ~SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeIntrinsicBalanceFactorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.IntrinsicBalanceFactor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute BallastFactorAdjustment
 */
class ReadBallastConfigurationBallastFactorAdjustment : public ReadAttribute {
public:
    ReadBallastConfigurationBallastFactorAdjustment()
        : ReadAttribute("ballast-factor-adjustment")
    {
    }

    ~ReadBallastConfigurationBallastFactorAdjustment() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeBallastFactorAdjustmentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.BallastFactorAdjustment response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration BallastFactorAdjustment read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationBallastFactorAdjustment : public WriteAttribute {
public:
    WriteBallastConfigurationBallastFactorAdjustment()
        : WriteAttribute("ballast-factor-adjustment")
    {
        AddArgument("attr-name", "ballast-factor-adjustment");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationBallastFactorAdjustment() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeBallastFactorAdjustmentWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError(
                                                                 "BallastConfiguration BallastFactorAdjustment write Error", error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationBallastFactorAdjustment : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationBallastFactorAdjustment()
        : SubscribeAttribute("ballast-factor-adjustment")
    {
    }

    ~SubscribeAttributeBallastConfigurationBallastFactorAdjustment() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBallastFactorAdjustmentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.BallastFactorAdjustment response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampQuantity
 */
class ReadBallastConfigurationLampQuantity : public ReadAttribute {
public:
    ReadBallastConfigurationLampQuantity()
        : ReadAttribute("lamp-quantity")
    {
    }

    ~ReadBallastConfigurationLampQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampQuantityWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampQuantity response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampQuantity read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationLampQuantity : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampQuantity()
        : SubscribeAttribute("lamp-quantity")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampQuantity() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampQuantityWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampQuantity response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampType
 */
class ReadBallastConfigurationLampType : public ReadAttribute {
public:
    ReadBallastConfigurationLampType()
        : ReadAttribute("lamp-type")
    {
    }

    ~ReadBallastConfigurationLampType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampTypeWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampType response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampType : public WriteAttribute {
public:
    WriteBallastConfigurationLampType()
        : WriteAttribute("lamp-type")
    {
        AddArgument("attr-name", "lamp-type");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLampTypeWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("BallastConfiguration LampType write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBallastConfigurationLampType : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampType()
        : SubscribeAttribute("lamp-type")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampManufacturer
 */
class ReadBallastConfigurationLampManufacturer : public ReadAttribute {
public:
    ReadBallastConfigurationLampManufacturer()
        : ReadAttribute("lamp-manufacturer")
    {
    }

    ~ReadBallastConfigurationLampManufacturer() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampManufacturerWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampManufacturer response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampManufacturer read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampManufacturer : public WriteAttribute {
public:
    WriteBallastConfigurationLampManufacturer()
        : WriteAttribute("lamp-manufacturer")
    {
        AddArgument("attr-name", "lamp-manufacturer");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampManufacturer() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLampManufacturerWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("BallastConfiguration LampManufacturer write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeBallastConfigurationLampManufacturer : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampManufacturer()
        : SubscribeAttribute("lamp-manufacturer")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampManufacturer() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampManufacturerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampManufacturer response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampRatedHours
 */
class ReadBallastConfigurationLampRatedHours : public ReadAttribute {
public:
    ReadBallastConfigurationLampRatedHours()
        : ReadAttribute("lamp-rated-hours")
    {
    }

    ~ReadBallastConfigurationLampRatedHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampRatedHoursWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampRatedHours response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampRatedHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampRatedHours : public WriteAttribute {
public:
    WriteBallastConfigurationLampRatedHours()
        : WriteAttribute("lamp-rated-hours")
    {
        AddArgument("attr-name", "lamp-rated-hours");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampRatedHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeLampRatedHoursWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("BallastConfiguration LampRatedHours write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeBallastConfigurationLampRatedHours : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampRatedHours()
        : SubscribeAttribute("lamp-rated-hours")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampRatedHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampRatedHoursWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampRatedHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampBurnHours
 */
class ReadBallastConfigurationLampBurnHours : public ReadAttribute {
public:
    ReadBallastConfigurationLampBurnHours()
        : ReadAttribute("lamp-burn-hours")
    {
    }

    ~ReadBallastConfigurationLampBurnHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000033) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampBurnHoursWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampBurnHours response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampBurnHours read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampBurnHours : public WriteAttribute {
public:
    WriteBallastConfigurationLampBurnHours()
        : WriteAttribute("lamp-burn-hours")
    {
        AddArgument("attr-name", "lamp-burn-hours");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampBurnHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeLampBurnHoursWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("BallastConfiguration LampBurnHours write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeBallastConfigurationLampBurnHours : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampBurnHours()
        : SubscribeAttribute("lamp-burn-hours")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampBurnHours() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000033) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampBurnHoursWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampBurnHours response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampAlarmMode
 */
class ReadBallastConfigurationLampAlarmMode : public ReadAttribute {
public:
    ReadBallastConfigurationLampAlarmMode()
        : ReadAttribute("lamp-alarm-mode")
    {
    }

    ~ReadBallastConfigurationLampAlarmMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000034) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampAlarmModeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampAlarmMode response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampAlarmMode read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampAlarmMode : public WriteAttribute {
public:
    WriteBallastConfigurationLampAlarmMode()
        : WriteAttribute("lamp-alarm-mode")
    {
        AddArgument("attr-name", "lamp-alarm-mode");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampAlarmMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeLampAlarmModeWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("BallastConfiguration LampAlarmMode write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeBallastConfigurationLampAlarmMode : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampAlarmMode()
        : SubscribeAttribute("lamp-alarm-mode")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampAlarmMode() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000034) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampAlarmModeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampAlarmMode response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LampBurnHoursTripPoint
 */
class ReadBallastConfigurationLampBurnHoursTripPoint : public ReadAttribute {
public:
    ReadBallastConfigurationLampBurnHoursTripPoint()
        : ReadAttribute("lamp-burn-hours-trip-point")
    {
    }

    ~ReadBallastConfigurationLampBurnHoursTripPoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x00000035) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeLampBurnHoursTripPointWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.LampBurnHoursTripPoint response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration LampBurnHoursTripPoint read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteBallastConfigurationLampBurnHoursTripPoint : public WriteAttribute {
public:
    WriteBallastConfigurationLampBurnHoursTripPoint()
        : WriteAttribute("lamp-burn-hours-trip-point")
    {
        AddArgument("attr-name", "lamp-burn-hours-trip-point");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteBallastConfigurationLampBurnHoursTripPoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) WriteAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster
            writeAttributeLampBurnHoursTripPointWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("BallastConfiguration LampBurnHoursTripPoint write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint()
        : SubscribeAttribute("lamp-burn-hours-trip-point")
    {
    }

    ~SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x00000035) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLampBurnHoursTripPointWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.LampBurnHoursTripPoint response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadBallastConfigurationGeneratedCommandList : public ReadAttribute {
public:
    ReadBallastConfigurationGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadBallastConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadBallastConfigurationAcceptedCommandList : public ReadAttribute {
public:
    ReadBallastConfigurationAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadBallastConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadBallastConfigurationAttributeList : public ReadAttribute {
public:
    ReadBallastConfigurationAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadBallastConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeBallastConfigurationAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadBallastConfigurationFeatureMap : public ReadAttribute {
public:
    ReadBallastConfigurationFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadBallastConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeBallastConfigurationFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadBallastConfigurationClusterRevision : public ReadAttribute {
public:
    ReadBallastConfigurationClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadBallastConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"BallastConfiguration.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("BallastConfiguration ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeBallastConfigurationClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeBallastConfigurationClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeBallastConfigurationClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000301) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterBallastConfiguration * cluster = [[MTRBaseClusterBallastConfiguration alloc] initWithDevice:device
                                                                                                       endpointID:@(endpointId)
                                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"BallastConfiguration.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster IlluminanceMeasurement                                      | 0x0400 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * LightSensorType                                                   | 0x0004 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadIlluminanceMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadIlluminanceMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadIlluminanceMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadIlluminanceMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadIlluminanceMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadIlluminanceMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadIlluminanceMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadIlluminanceMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadIlluminanceMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadIlluminanceMeasurementTolerance : public ReadAttribute {
public:
    ReadIlluminanceMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadIlluminanceMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeToleranceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LightSensorType
 */
class ReadIlluminanceMeasurementLightSensorType : public ReadAttribute {
public:
    ReadIlluminanceMeasurementLightSensorType()
        : ReadAttribute("light-sensor-type")
    {
    }

    ~ReadIlluminanceMeasurementLightSensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeLightSensorTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.LightSensorType response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement LightSensorType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementLightSensorType : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementLightSensorType()
        : SubscribeAttribute("light-sensor-type")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementLightSensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLightSensorTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.LightSensorType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadIlluminanceMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadIlluminanceMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadIlluminanceMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadIlluminanceMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadIlluminanceMeasurementAttributeList : public ReadAttribute {
public:
    ReadIlluminanceMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadIlluminanceMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadIlluminanceMeasurementFeatureMap : public ReadAttribute {
public:
    ReadIlluminanceMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadIlluminanceMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadIlluminanceMeasurementClusterRevision : public ReadAttribute {
public:
    ReadIlluminanceMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadIlluminanceMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"IlluminanceMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("IlluminanceMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeIlluminanceMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeIlluminanceMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeIlluminanceMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000400) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterIlluminanceMeasurement * cluster =
            [[MTRBaseClusterIlluminanceMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"IlluminanceMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TemperatureMeasurement                                      | 0x0402 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadTemperatureMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadTemperatureMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadTemperatureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadTemperatureMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadTemperatureMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadTemperatureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadTemperatureMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadTemperatureMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadTemperatureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadTemperatureMeasurementTolerance : public ReadAttribute {
public:
    ReadTemperatureMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadTemperatureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeToleranceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTemperatureMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadTemperatureMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTemperatureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTemperatureMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadTemperatureMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTemperatureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTemperatureMeasurementAttributeList : public ReadAttribute {
public:
    ReadTemperatureMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTemperatureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTemperatureMeasurementFeatureMap : public ReadAttribute {
public:
    ReadTemperatureMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTemperatureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTemperatureMeasurementClusterRevision : public ReadAttribute {
public:
    ReadTemperatureMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTemperatureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TemperatureMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TemperatureMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTemperatureMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTemperatureMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTemperatureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000402) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTemperatureMeasurement * cluster =
            [[MTRBaseClusterTemperatureMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TemperatureMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster PressureMeasurement                                         | 0x0403 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * ScaledValue                                                       | 0x0010 |
| * MinScaledValue                                                    | 0x0011 |
| * MaxScaledValue                                                    | 0x0012 |
| * ScaledTolerance                                                   | 0x0013 |
| * Scale                                                             | 0x0014 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadPressureMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadPressureMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadPressureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadPressureMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadPressureMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadPressureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadPressureMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadPressureMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadPressureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadPressureMeasurementTolerance : public ReadAttribute {
public:
    ReadPressureMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadPressureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributePressureMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeToleranceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScaledValue
 */
class ReadPressureMeasurementScaledValue : public ReadAttribute {
public:
    ReadPressureMeasurementScaledValue()
        : ReadAttribute("scaled-value")
    {
    }

    ~ReadPressureMeasurementScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeScaledValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.ScaledValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement ScaledValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementScaledValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementScaledValue()
        : SubscribeAttribute("scaled-value")
    {
    }

    ~SubscribeAttributePressureMeasurementScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeScaledValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.ScaledValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinScaledValue
 */
class ReadPressureMeasurementMinScaledValue : public ReadAttribute {
public:
    ReadPressureMeasurementMinScaledValue()
        : ReadAttribute("min-scaled-value")
    {
    }

    ~ReadPressureMeasurementMinScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMinScaledValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MinScaledValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MinScaledValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMinScaledValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMinScaledValue()
        : SubscribeAttribute("min-scaled-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMinScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinScaledValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MinScaledValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxScaledValue
 */
class ReadPressureMeasurementMaxScaledValue : public ReadAttribute {
public:
    ReadPressureMeasurementMaxScaledValue()
        : ReadAttribute("max-scaled-value")
    {
    }

    ~ReadPressureMeasurementMaxScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeMaxScaledValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.MaxScaledValue response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement MaxScaledValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementMaxScaledValue : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementMaxScaledValue()
        : SubscribeAttribute("max-scaled-value")
    {
    }

    ~SubscribeAttributePressureMeasurementMaxScaledValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxScaledValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.MaxScaledValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ScaledTolerance
 */
class ReadPressureMeasurementScaledTolerance : public ReadAttribute {
public:
    ReadPressureMeasurementScaledTolerance()
        : ReadAttribute("scaled-tolerance")
    {
    }

    ~ReadPressureMeasurementScaledTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeScaledToleranceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.ScaledTolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement ScaledTolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementScaledTolerance : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementScaledTolerance()
        : SubscribeAttribute("scaled-tolerance")
    {
    }

    ~SubscribeAttributePressureMeasurementScaledTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeScaledToleranceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.ScaledTolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Scale
 */
class ReadPressureMeasurementScale : public ReadAttribute {
public:
    ReadPressureMeasurementScale()
        : ReadAttribute("scale")
    {
    }

    ~ReadPressureMeasurementScale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeScaleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.Scale response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement Scale read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementScale : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementScale()
        : SubscribeAttribute("scale")
    {
    }

    ~SubscribeAttributePressureMeasurementScale() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeScaleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.Scale response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadPressureMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadPressureMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadPressureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributePressureMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadPressureMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadPressureMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadPressureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributePressureMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadPressureMeasurementAttributeList : public ReadAttribute {
public:
    ReadPressureMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadPressureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributePressureMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadPressureMeasurementFeatureMap : public ReadAttribute {
public:
    ReadPressureMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadPressureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributePressureMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadPressureMeasurementClusterRevision : public ReadAttribute {
public:
    ReadPressureMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadPressureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"PressureMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("PressureMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributePressureMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributePressureMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributePressureMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000403) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterPressureMeasurement * cluster = [[MTRBaseClusterPressureMeasurement alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"PressureMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster FlowMeasurement                                             | 0x0404 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadFlowMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadFlowMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadFlowMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeFlowMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadFlowMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadFlowMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadFlowMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeFlowMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadFlowMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadFlowMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadFlowMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeFlowMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadFlowMeasurementTolerance : public ReadAttribute {
public:
    ReadFlowMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadFlowMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeFlowMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeToleranceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadFlowMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadFlowMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadFlowMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadFlowMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadFlowMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadFlowMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadFlowMeasurementAttributeList : public ReadAttribute {
public:
    ReadFlowMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadFlowMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeFlowMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadFlowMeasurementFeatureMap : public ReadAttribute {
public:
    ReadFlowMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadFlowMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeFlowMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadFlowMeasurementClusterRevision : public ReadAttribute {
public:
    ReadFlowMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadFlowMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"FlowMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("FlowMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeFlowMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeFlowMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeFlowMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000404) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterFlowMeasurement * cluster = [[MTRBaseClusterFlowMeasurement alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"FlowMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster RelativeHumidityMeasurement                                 | 0x0405 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasuredValue                                                     | 0x0000 |
| * MinMeasuredValue                                                  | 0x0001 |
| * MaxMeasuredValue                                                  | 0x0002 |
| * Tolerance                                                         | 0x0003 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MeasuredValue
 */
class ReadRelativeHumidityMeasurementMeasuredValue : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementMeasuredValue()
        : ReadAttribute("measured-value")
    {
    }

    ~ReadRelativeHumidityMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.MeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement MeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementMeasuredValue()
        : SubscribeAttribute("measured-value")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.MeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MinMeasuredValue
 */
class ReadRelativeHumidityMeasurementMinMeasuredValue : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementMinMeasuredValue()
        : ReadAttribute("min-measured-value")
    {
    }

    ~ReadRelativeHumidityMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMinMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.MinMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement MinMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue()
        : SubscribeAttribute("min-measured-value")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMinMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.MinMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MaxMeasuredValue
 */
class ReadRelativeHumidityMeasurementMaxMeasuredValue : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementMaxMeasuredValue()
        : ReadAttribute("max-measured-value")
    {
    }

    ~ReadRelativeHumidityMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeMaxMeasuredValueWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.MaxMeasuredValue response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement MaxMeasuredValue read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue()
        : SubscribeAttribute("max-measured-value")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMaxMeasuredValueWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.MaxMeasuredValue response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Tolerance
 */
class ReadRelativeHumidityMeasurementTolerance : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementTolerance()
        : ReadAttribute("tolerance")
    {
    }

    ~ReadRelativeHumidityMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeToleranceWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.Tolerance response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement Tolerance read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementTolerance : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementTolerance()
        : SubscribeAttribute("tolerance")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementTolerance() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeToleranceWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.Tolerance response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadRelativeHumidityMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadRelativeHumidityMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadRelativeHumidityMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadRelativeHumidityMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadRelativeHumidityMeasurementAttributeList : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadRelativeHumidityMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadRelativeHumidityMeasurementFeatureMap : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadRelativeHumidityMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadRelativeHumidityMeasurementClusterRevision : public ReadAttribute {
public:
    ReadRelativeHumidityMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadRelativeHumidityMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"RelativeHumidityMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("RelativeHumidityMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeRelativeHumidityMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeRelativeHumidityMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeRelativeHumidityMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000405) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterRelativeHumidityMeasurement * cluster =
            [[MTRBaseClusterRelativeHumidityMeasurement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"RelativeHumidityMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster OccupancySensing                                            | 0x0406 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Occupancy                                                         | 0x0000 |
| * OccupancySensorType                                               | 0x0001 |
| * OccupancySensorTypeBitmap                                         | 0x0002 |
| * PirOccupiedToUnoccupiedDelay                                      | 0x0010 |
| * PirUnoccupiedToOccupiedDelay                                      | 0x0011 |
| * PirUnoccupiedToOccupiedThreshold                                  | 0x0012 |
| * UltrasonicOccupiedToUnoccupiedDelay                               | 0x0020 |
| * UltrasonicUnoccupiedToOccupiedDelay                               | 0x0021 |
| * UltrasonicUnoccupiedToOccupiedThreshold                           | 0x0022 |
| * PhysicalContactOccupiedToUnoccupiedDelay                          | 0x0030 |
| * PhysicalContactUnoccupiedToOccupiedDelay                          | 0x0031 |
| * PhysicalContactUnoccupiedToOccupiedThreshold                      | 0x0032 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute Occupancy
 */
class ReadOccupancySensingOccupancy : public ReadAttribute {
public:
    ReadOccupancySensingOccupancy()
        : ReadAttribute("occupancy")
    {
    }

    ~ReadOccupancySensingOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeOccupancyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.Occupancy response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing Occupancy read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingOccupancy : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingOccupancy()
        : SubscribeAttribute("occupancy")
    {
    }

    ~SubscribeAttributeOccupancySensingOccupancy() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupancyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.Occupancy response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupancySensorType
 */
class ReadOccupancySensingOccupancySensorType : public ReadAttribute {
public:
    ReadOccupancySensingOccupancySensorType()
        : ReadAttribute("occupancy-sensor-type")
    {
    }

    ~ReadOccupancySensingOccupancySensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeOccupancySensorTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.OccupancySensorType response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing OccupancySensorType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingOccupancySensorType : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingOccupancySensorType()
        : SubscribeAttribute("occupancy-sensor-type")
    {
    }

    ~SubscribeAttributeOccupancySensingOccupancySensorType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupancySensorTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.OccupancySensorType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OccupancySensorTypeBitmap
 */
class ReadOccupancySensingOccupancySensorTypeBitmap : public ReadAttribute {
public:
    ReadOccupancySensingOccupancySensorTypeBitmap()
        : ReadAttribute("occupancy-sensor-type-bitmap")
    {
    }

    ~ReadOccupancySensingOccupancySensorTypeBitmap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeOccupancySensorTypeBitmapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.OccupancySensorTypeBitmap response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing OccupancySensorTypeBitmap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap()
        : SubscribeAttribute("occupancy-sensor-type-bitmap")
    {
    }

    ~SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOccupancySensorTypeBitmapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.OccupancySensorTypeBitmap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PirOccupiedToUnoccupiedDelay
 */
class ReadOccupancySensingPirOccupiedToUnoccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPirOccupiedToUnoccupiedDelay()
        : ReadAttribute("pir-occupied-to-unoccupied-delay")
    {
    }

    ~ReadOccupancySensingPirOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePirOccupiedToUnoccupiedDelayWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PirOccupiedToUnoccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PirOccupiedToUnoccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPirOccupiedToUnoccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPirOccupiedToUnoccupiedDelay()
        : WriteAttribute("pir-occupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "pir-occupied-to-unoccupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPirOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributePirOccupiedToUnoccupiedDelayWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("OccupancySensing PirOccupiedToUnoccupiedDelay write Error",
                                                                 error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay()
        : SubscribeAttribute("pir-occupied-to-unoccupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePirOccupiedToUnoccupiedDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirOccupiedToUnoccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PirUnoccupiedToOccupiedDelay
 */
class ReadOccupancySensingPirUnoccupiedToOccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPirUnoccupiedToOccupiedDelay()
        : ReadAttribute("pir-unoccupied-to-occupied-delay")
    {
    }

    ~ReadOccupancySensingPirUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePirUnoccupiedToOccupiedDelayWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PirUnoccupiedToOccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPirUnoccupiedToOccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPirUnoccupiedToOccupiedDelay()
        : WriteAttribute("pir-unoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "pir-unoccupied-to-occupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPirUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributePirUnoccupiedToOccupiedDelayWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError("OccupancySensing PirUnoccupiedToOccupiedDelay write Error",
                                                                 error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay()
        : SubscribeAttribute("pir-unoccupied-to-occupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePirUnoccupiedToOccupiedDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PirUnoccupiedToOccupiedThreshold
 */
class ReadOccupancySensingPirUnoccupiedToOccupiedThreshold : public ReadAttribute {
public:
    ReadOccupancySensingPirUnoccupiedToOccupiedThreshold()
        : ReadAttribute("pir-unoccupied-to-occupied-threshold")
    {
    }

    ~ReadOccupancySensingPirUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster
            readAttributePirUnoccupiedToOccupiedThresholdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedThreshold response %@", [value description]);
                if (error != nil) {
                    LogNSError("OccupancySensing PirUnoccupiedToOccupiedThreshold read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPirUnoccupiedToOccupiedThreshold : public WriteAttribute {
public:
    WriteOccupancySensingPirUnoccupiedToOccupiedThreshold()
        : WriteAttribute("pir-unoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "pir-unoccupied-to-occupied-threshold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPirUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributePirUnoccupiedToOccupiedThresholdWithValue:value
                                                                  params:params
                                                              completion:^(NSError * _Nullable error) {
                                                                  if (error != nil) {
                                                                      LogNSError("OccupancySensing "
                                                                                 "PirUnoccupiedToOccupiedThreshold write Error",
                                                                          error);
                                                                  }
                                                                  SetCommandExitStatus(error);
                                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold()
        : SubscribeAttribute("pir-unoccupied-to-occupied-threshold")
    {
    }

    ~SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePirUnoccupiedToOccupiedThresholdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PirUnoccupiedToOccupiedThreshold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UltrasonicOccupiedToUnoccupiedDelay
 */
class ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay()
        : ReadAttribute("ultrasonic-occupied-to-unoccupied-delay")
    {
    }

    ~ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeUltrasonicOccupiedToUnoccupiedDelayWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.UltrasonicOccupiedToUnoccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing UltrasonicOccupiedToUnoccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay()
        : WriteAttribute("ultrasonic-occupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "ultrasonic-occupied-to-unoccupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeUltrasonicOccupiedToUnoccupiedDelayWithValue:value
                                                                params:params
                                                            completion:^(NSError * _Nullable error) {
                                                                if (error != nil) {
                                                                    LogNSError("OccupancySensing "
                                                                               "UltrasonicOccupiedToUnoccupiedDelay write Error",
                                                                        error);
                                                                }
                                                                SetCommandExitStatus(error);
                                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay()
        : SubscribeAttribute("ultrasonic-occupied-to-unoccupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUltrasonicOccupiedToUnoccupiedDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.UltrasonicOccupiedToUnoccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UltrasonicUnoccupiedToOccupiedDelay
 */
class ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay()
        : ReadAttribute("ultrasonic-unoccupied-to-occupied-delay")
    {
    }

    ~ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeUltrasonicUnoccupiedToOccupiedDelayWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing UltrasonicUnoccupiedToOccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay()
        : WriteAttribute("ultrasonic-unoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "ultrasonic-unoccupied-to-occupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeUltrasonicUnoccupiedToOccupiedDelayWithValue:value
                                                                params:params
                                                            completion:^(NSError * _Nullable error) {
                                                                if (error != nil) {
                                                                    LogNSError("OccupancySensing "
                                                                               "UltrasonicUnoccupiedToOccupiedDelay write Error",
                                                                        error);
                                                                }
                                                                SetCommandExitStatus(error);
                                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay()
        : SubscribeAttribute("ultrasonic-unoccupied-to-occupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUltrasonicUnoccupiedToOccupiedDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute UltrasonicUnoccupiedToOccupiedThreshold
 */
class ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold : public ReadAttribute {
public:
    ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold()
        : ReadAttribute("ultrasonic-unoccupied-to-occupied-threshold")
    {
    }

    ~ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeUltrasonicUnoccupiedToOccupiedThresholdWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedThreshold response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing UltrasonicUnoccupiedToOccupiedThreshold read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold : public WriteAttribute {
public:
    WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold()
        : WriteAttribute("ultrasonic-unoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "ultrasonic-unoccupied-to-occupied-threshold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster
            writeAttributeUltrasonicUnoccupiedToOccupiedThresholdWithValue:value
                                                                    params:params
                                                                completion:^(NSError * _Nullable error) {
                                                                    if (error != nil) {
                                                                        LogNSError(
                                                                            "OccupancySensing "
                                                                            "UltrasonicUnoccupiedToOccupiedThreshold write Error",
                                                                            error);
                                                                    }
                                                                    SetCommandExitStatus(error);
                                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold()
        : SubscribeAttribute("ultrasonic-unoccupied-to-occupied-threshold")
    {
    }

    ~SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUltrasonicUnoccupiedToOccupiedThresholdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.UltrasonicUnoccupiedToOccupiedThreshold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalContactOccupiedToUnoccupiedDelay
 */
class ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay()
        : ReadAttribute("physical-contact-occupied-to-unoccupied-delay")
    {
    }

    ~ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePhysicalContactOccupiedToUnoccupiedDelayWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PhysicalContactOccupiedToUnoccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PhysicalContactOccupiedToUnoccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay()
        : WriteAttribute("physical-contact-occupied-to-unoccupied-delay")
    {
        AddArgument("attr-name", "physical-contact-occupied-to-unoccupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributePhysicalContactOccupiedToUnoccupiedDelayWithValue:value
                                                                     params:params
                                                                 completion:^(NSError * _Nullable error) {
                                                                     if (error != nil) {
                                                                         LogNSError(
                                                                             "OccupancySensing "
                                                                             "PhysicalContactOccupiedToUnoccupiedDelay write Error",
                                                                             error);
                                                                     }
                                                                     SetCommandExitStatus(error);
                                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay()
        : SubscribeAttribute("physical-contact-occupied-to-unoccupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalContactOccupiedToUnoccupiedDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PhysicalContactOccupiedToUnoccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalContactUnoccupiedToOccupiedDelay
 */
class ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay : public ReadAttribute {
public:
    ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay()
        : ReadAttribute("physical-contact-unoccupied-to-occupied-delay")
    {
    }

    ~ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePhysicalContactUnoccupiedToOccupiedDelayWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedDelay response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PhysicalContactUnoccupiedToOccupiedDelay read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay : public WriteAttribute {
public:
    WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay()
        : WriteAttribute("physical-contact-unoccupied-to-occupied-delay")
    {
        AddArgument("attr-name", "physical-contact-unoccupied-to-occupied-delay");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributePhysicalContactUnoccupiedToOccupiedDelayWithValue:value
                                                                     params:params
                                                                 completion:^(NSError * _Nullable error) {
                                                                     if (error != nil) {
                                                                         LogNSError(
                                                                             "OccupancySensing "
                                                                             "PhysicalContactUnoccupiedToOccupiedDelay write Error",
                                                                             error);
                                                                     }
                                                                     SetCommandExitStatus(error);
                                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay()
        : SubscribeAttribute("physical-contact-unoccupied-to-occupied-delay")
    {
    }

    ~SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalContactUnoccupiedToOccupiedDelayWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedDelay response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhysicalContactUnoccupiedToOccupiedThreshold
 */
class ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold : public ReadAttribute {
public:
    ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold()
        : ReadAttribute("physical-contact-unoccupied-to-occupied-threshold")
    {
    }

    ~ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributePhysicalContactUnoccupiedToOccupiedThresholdWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedThreshold response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing PhysicalContactUnoccupiedToOccupiedThreshold read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold : public WriteAttribute {
public:
    WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold()
        : WriteAttribute("physical-contact-unoccupied-to-occupied-threshold")
    {
        AddArgument("attr-name", "physical-contact-unoccupied-to-occupied-threshold");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributePhysicalContactUnoccupiedToOccupiedThresholdWithValue:value
                                                                              params:params
                                                                          completion:^(NSError * _Nullable error) {
                                                                              if (error != nil) {
                                                                                  LogNSError("OccupancySensing "
                                                                                             "PhysicalContactUnoccupiedToOccupiedTh"
                                                                                             "reshold write Error",
                                                                                      error);
                                                                              }
                                                                              SetCommandExitStatus(error);
                                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold()
        : SubscribeAttribute("physical-contact-unoccupied-to-occupied-threshold")
    {
    }

    ~SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhysicalContactUnoccupiedToOccupiedThresholdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.PhysicalContactUnoccupiedToOccupiedThreshold response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadOccupancySensingGeneratedCommandList : public ReadAttribute {
public:
    ReadOccupancySensingGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadOccupancySensingGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeOccupancySensingGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadOccupancySensingAcceptedCommandList : public ReadAttribute {
public:
    ReadOccupancySensingAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadOccupancySensingAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeOccupancySensingAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadOccupancySensingAttributeList : public ReadAttribute {
public:
    ReadOccupancySensingAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadOccupancySensingAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeOccupancySensingAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadOccupancySensingFeatureMap : public ReadAttribute {
public:
    ReadOccupancySensingFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadOccupancySensingFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeOccupancySensingFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadOccupancySensingClusterRevision : public ReadAttribute {
public:
    ReadOccupancySensingClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadOccupancySensingClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"OccupancySensing.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("OccupancySensing ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeOccupancySensingClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeOccupancySensingClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeOccupancySensingClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000406) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterOccupancySensing * cluster = [[MTRBaseClusterOccupancySensing alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"OccupancySensing.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster WakeOnLan                                                   | 0x0503 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MACAddress                                                        | 0x0000 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute MACAddress
 */
class ReadWakeOnLanMACAddress : public ReadAttribute {
public:
    ReadWakeOnLanMACAddress()
        : ReadAttribute("macaddress")
    {
    }

    ~ReadWakeOnLanMACAddress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeMACAddressWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.MACAddress response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan MACAddress read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanMACAddress : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanMACAddress()
        : SubscribeAttribute("macaddress")
    {
    }

    ~SubscribeAttributeWakeOnLanMACAddress() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMACAddressWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.MACAddress response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadWakeOnLanGeneratedCommandList : public ReadAttribute {
public:
    ReadWakeOnLanGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadWakeOnLanGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeWakeOnLanGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadWakeOnLanAcceptedCommandList : public ReadAttribute {
public:
    ReadWakeOnLanAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadWakeOnLanAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeWakeOnLanAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadWakeOnLanAttributeList : public ReadAttribute {
public:
    ReadWakeOnLanAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadWakeOnLanAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeWakeOnLanAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadWakeOnLanFeatureMap : public ReadAttribute {
public:
    ReadWakeOnLanFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadWakeOnLanFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeWakeOnLanFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadWakeOnLanClusterRevision : public ReadAttribute {
public:
    ReadWakeOnLanClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadWakeOnLanClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"WakeOnLan.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("WakeOnLan ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeWakeOnLanClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeWakeOnLanClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeWakeOnLanClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000503) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterWakeOnLan * cluster = [[MTRBaseClusterWakeOnLan alloc] initWithDevice:device
                                                                                 endpointID:@(endpointId)
                                                                                      queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"WakeOnLan.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster Channel                                                     | 0x0504 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * ChangeChannel                                                     |   0x00 |
| * ChangeChannelByNumber                                             |   0x02 |
| * SkipChannel                                                       |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * ChannelList                                                       | 0x0000 |
| * Lineup                                                            | 0x0001 |
| * CurrentChannel                                                    | 0x0002 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command ChangeChannel
 */
class ChannelChangeChannel : public ClusterCommand {
public:
    ChannelChangeChannel()
        : ClusterCommand("change-channel")
    {
        AddArgument("Match", &mRequest.match);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRChannelClusterChangeChannelParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.match = [[NSString alloc] initWithBytes:mRequest.match.data()
                                                length:mRequest.match.size()
                                              encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster changeChannelWithParams:params
                                  completion:^(
                                      MTRChannelClusterChangeChannelResponseParams * _Nullable values, NSError * _Nullable error) {
                                      NSLog(@"Values: %@", values);
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Channel::Commands::ChangeChannel::Type mRequest;
};

/*
 * Command ChangeChannelByNumber
 */
class ChannelChangeChannelByNumber : public ClusterCommand {
public:
    ChannelChangeChannelByNumber()
        : ClusterCommand("change-channel-by-number")
    {
        AddArgument("MajorNumber", 0, UINT16_MAX, &mRequest.majorNumber);
        AddArgument("MinorNumber", 0, UINT16_MAX, &mRequest.minorNumber);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRChannelClusterChangeChannelByNumberParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.majorNumber = [NSNumber numberWithUnsignedShort:mRequest.majorNumber];
        params.minorNumber = [NSNumber numberWithUnsignedShort:mRequest.minorNumber];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster changeChannelByNumberWithParams:params
                                          completion:^(NSError * _Nullable error) {
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Channel::Commands::ChangeChannelByNumber::Type mRequest;
};

/*
 * Command SkipChannel
 */
class ChannelSkipChannel : public ClusterCommand {
public:
    ChannelSkipChannel()
        : ClusterCommand("skip-channel")
    {
        AddArgument("Count", 0, UINT16_MAX, &mRequest.count);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRChannelClusterSkipChannelParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.count = [NSNumber numberWithUnsignedShort:mRequest.count];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster skipChannelWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::Channel::Commands::SkipChannel::Type mRequest;
};

/*
 * Attribute ChannelList
 */
class ReadChannelChannelList : public ReadAttribute {
public:
    ReadChannelChannelList()
        : ReadAttribute("channel-list")
    {
    }

    ~ReadChannelChannelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeChannelListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.ChannelList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel ChannelList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelChannelList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelChannelList()
        : SubscribeAttribute("channel-list")
    {
    }

    ~SubscribeAttributeChannelChannelList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeChannelListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.ChannelList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Lineup
 */
class ReadChannelLineup : public ReadAttribute {
public:
    ReadChannelLineup()
        : ReadAttribute("lineup")
    {
    }

    ~ReadChannelLineup() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeLineupWithCompletion:^(MTRChannelClusterLineupInfo * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.Lineup response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel Lineup read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelLineup : public SubscribeAttribute {
public:
    SubscribeAttributeChannelLineup()
        : SubscribeAttribute("lineup")
    {
    }

    ~SubscribeAttributeChannelLineup() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLineupWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRChannelClusterLineupInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.Lineup response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentChannel
 */
class ReadChannelCurrentChannel : public ReadAttribute {
public:
    ReadChannelCurrentChannel()
        : ReadAttribute("current-channel")
    {
    }

    ~ReadChannelCurrentChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster
            readAttributeCurrentChannelWithCompletion:^(MTRChannelClusterChannelInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.CurrentChannel response %@", [value description]);
                if (error != nil) {
                    LogNSError("Channel CurrentChannel read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelCurrentChannel : public SubscribeAttribute {
public:
    SubscribeAttributeChannelCurrentChannel()
        : SubscribeAttribute("current-channel")
    {
    }

    ~SubscribeAttributeChannelCurrentChannel() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentChannelWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRChannelClusterChannelInfo * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.CurrentChannel response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadChannelGeneratedCommandList : public ReadAttribute {
public:
    ReadChannelGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadChannelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeChannelGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadChannelAcceptedCommandList : public ReadAttribute {
public:
    ReadChannelAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadChannelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeChannelAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadChannelAttributeList : public ReadAttribute {
public:
    ReadChannelAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadChannelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeChannelAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeChannelAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadChannelFeatureMap : public ReadAttribute {
public:
    ReadChannelFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadChannelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeChannelFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeChannelFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadChannelClusterRevision : public ReadAttribute {
public:
    ReadChannelClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadChannelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"Channel.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("Channel ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeChannelClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeChannelClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeChannelClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000504) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterChannel * cluster = [[MTRBaseClusterChannel alloc] initWithDevice:device
                                                                             endpointID:@(endpointId)
                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"Channel.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TargetNavigator                                             | 0x0505 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * NavigateTarget                                                    |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * TargetList                                                        | 0x0000 |
| * CurrentTarget                                                     | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command NavigateTarget
 */
class TargetNavigatorNavigateTarget : public ClusterCommand {
public:
    TargetNavigatorNavigateTarget()
        : ClusterCommand("navigate-target")
    {
        AddArgument("Target", 0, UINT8_MAX, &mRequest.target);
        AddArgument("Data", &mRequest.data);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRTargetNavigatorClusterNavigateTargetParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.target = [NSNumber numberWithUnsignedChar:mRequest.target];
        if (mRequest.data.HasValue()) {
            params.data = [[NSString alloc] initWithBytes:mRequest.data.Value().data()
                                                   length:mRequest.data.Value().size()
                                                 encoding:NSUTF8StringEncoding];
        } else {
            params.data = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster navigateTargetWithParams:params
                                   completion:^(MTRTargetNavigatorClusterNavigateTargetResponseParams * _Nullable values,
                                       NSError * _Nullable error) {
                                       NSLog(@"Values: %@", values);
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TargetNavigator::Commands::NavigateTarget::Type mRequest;
};

/*
 * Attribute TargetList
 */
class ReadTargetNavigatorTargetList : public ReadAttribute {
public:
    ReadTargetNavigatorTargetList()
        : ReadAttribute("target-list")
    {
    }

    ~ReadTargetNavigatorTargetList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeTargetListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.TargetList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator TargetList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorTargetList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorTargetList()
        : SubscribeAttribute("target-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorTargetList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTargetListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.TargetList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentTarget
 */
class ReadTargetNavigatorCurrentTarget : public ReadAttribute {
public:
    ReadTargetNavigatorCurrentTarget()
        : ReadAttribute("current-target")
    {
    }

    ~ReadTargetNavigatorCurrentTarget() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeCurrentTargetWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.CurrentTarget response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator CurrentTarget read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorCurrentTarget : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorCurrentTarget()
        : SubscribeAttribute("current-target")
    {
    }

    ~SubscribeAttributeTargetNavigatorCurrentTarget() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentTargetWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.CurrentTarget response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTargetNavigatorGeneratedCommandList : public ReadAttribute {
public:
    ReadTargetNavigatorGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTargetNavigatorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTargetNavigatorAcceptedCommandList : public ReadAttribute {
public:
    ReadTargetNavigatorAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTargetNavigatorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTargetNavigatorAttributeList : public ReadAttribute {
public:
    ReadTargetNavigatorAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTargetNavigatorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTargetNavigatorAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTargetNavigatorFeatureMap : public ReadAttribute {
public:
    ReadTargetNavigatorFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTargetNavigatorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTargetNavigatorFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTargetNavigatorClusterRevision : public ReadAttribute {
public:
    ReadTargetNavigatorClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTargetNavigatorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TargetNavigator.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TargetNavigator ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTargetNavigatorClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTargetNavigatorClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTargetNavigatorClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000505) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTargetNavigator * cluster = [[MTRBaseClusterTargetNavigator alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TargetNavigator.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster MediaPlayback                                               | 0x0506 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Play                                                              |   0x00 |
| * Pause                                                             |   0x01 |
| * StopPlayback                                                      |   0x02 |
| * StartOver                                                         |   0x03 |
| * Previous                                                          |   0x04 |
| * Next                                                              |   0x05 |
| * Rewind                                                            |   0x06 |
| * FastForward                                                       |   0x07 |
| * SkipForward                                                       |   0x08 |
| * SkipBackward                                                      |   0x09 |
| * Seek                                                              |   0x0B |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * CurrentState                                                      | 0x0000 |
| * StartTime                                                         | 0x0001 |
| * Duration                                                          | 0x0002 |
| * SampledPosition                                                   | 0x0003 |
| * PlaybackSpeed                                                     | 0x0004 |
| * SeekRangeEnd                                                      | 0x0005 |
| * SeekRangeStart                                                    | 0x0006 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command Play
 */
class MediaPlaybackPlay : public ClusterCommand {
public:
    MediaPlaybackPlay()
        : ClusterCommand("play")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterPlayParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster playWithParams:params
                         completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Pause
 */
class MediaPlaybackPause : public ClusterCommand {
public:
    MediaPlaybackPause()
        : ClusterCommand("pause")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterPauseParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                pauseWithParams:params
                     completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                         NSLog(@"Values: %@", values);
                         responsesNeeded--;
                         if (error != nil) {
                             mError = error;
                             LogNSError("Error", error);
                         }
                         if (responsesNeeded == 0) {
                             SetCommandExitStatus(mError);
                         }
                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command StopPlayback
 */
class MediaPlaybackStopPlayback : public ClusterCommand {
public:
    MediaPlaybackStopPlayback()
        : ClusterCommand("stop-playback")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterStopPlaybackParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopPlaybackWithParams:params
                                 completion:^(
                                     MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command StartOver
 */
class MediaPlaybackStartOver : public ClusterCommand {
public:
    MediaPlaybackStartOver()
        : ClusterCommand("start-over")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterStartOverParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                startOverWithParams:params
                         completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Previous
 */
class MediaPlaybackPrevious : public ClusterCommand {
public:
    MediaPlaybackPrevious()
        : ClusterCommand("previous")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterPreviousParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                previousWithParams:params
                        completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                            NSLog(@"Values: %@", values);
                            responsesNeeded--;
                            if (error != nil) {
                                mError = error;
                                LogNSError("Error", error);
                            }
                            if (responsesNeeded == 0) {
                                SetCommandExitStatus(mError);
                            }
                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Next
 */
class MediaPlaybackNext : public ClusterCommand {
public:
    MediaPlaybackNext()
        : ClusterCommand("next")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterNextParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster nextWithParams:params
                         completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command Rewind
 */
class MediaPlaybackRewind : public ClusterCommand {
public:
    MediaPlaybackRewind()
        : ClusterCommand("rewind")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterRewindParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                rewindWithParams:params
                      completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                          NSLog(@"Values: %@", values);
                          responsesNeeded--;
                          if (error != nil) {
                              mError = error;
                              LogNSError("Error", error);
                          }
                          if (responsesNeeded == 0) {
                              SetCommandExitStatus(mError);
                          }
                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command FastForward
 */
class MediaPlaybackFastForward : public ClusterCommand {
public:
    MediaPlaybackFastForward()
        : ClusterCommand("fast-forward")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterFastForwardParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster fastForwardWithParams:params
                                completion:^(
                                    MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command SkipForward
 */
class MediaPlaybackSkipForward : public ClusterCommand {
public:
    MediaPlaybackSkipForward()
        : ClusterCommand("skip-forward")
    {
        AddArgument("DeltaPositionMilliseconds", 0, UINT64_MAX, &mRequest.deltaPositionMilliseconds);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterSkipForwardParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.deltaPositionMilliseconds = [NSNumber numberWithUnsignedLongLong:mRequest.deltaPositionMilliseconds];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster skipForwardWithParams:params
                                completion:^(
                                    MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaPlayback::Commands::SkipForward::Type mRequest;
};

/*
 * Command SkipBackward
 */
class MediaPlaybackSkipBackward : public ClusterCommand {
public:
    MediaPlaybackSkipBackward()
        : ClusterCommand("skip-backward")
    {
        AddArgument("DeltaPositionMilliseconds", 0, UINT64_MAX, &mRequest.deltaPositionMilliseconds);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterSkipBackwardParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.deltaPositionMilliseconds = [NSNumber numberWithUnsignedLongLong:mRequest.deltaPositionMilliseconds];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster skipBackwardWithParams:params
                                 completion:^(
                                     MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaPlayback::Commands::SkipBackward::Type mRequest;
};

/*
 * Command Seek
 */
class MediaPlaybackSeek : public ClusterCommand {
public:
    MediaPlaybackSeek()
        : ClusterCommand("seek")
    {
        AddArgument("Position", 0, UINT64_MAX, &mRequest.position);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRMediaPlaybackClusterSeekParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.position = [NSNumber numberWithUnsignedLongLong:mRequest.position];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster seekWithParams:params
                         completion:^(MTRMediaPlaybackClusterPlaybackResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaPlayback::Commands::Seek::Type mRequest;
};

/*
 * Attribute CurrentState
 */
class ReadMediaPlaybackCurrentState : public ReadAttribute {
public:
    ReadMediaPlaybackCurrentState()
        : ReadAttribute("current-state")
    {
    }

    ~ReadMediaPlaybackCurrentState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeCurrentStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.CurrentState response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback CurrentState read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackCurrentState : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackCurrentState()
        : SubscribeAttribute("current-state")
    {
    }

    ~SubscribeAttributeMediaPlaybackCurrentState() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentStateWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.CurrentState response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StartTime
 */
class ReadMediaPlaybackStartTime : public ReadAttribute {
public:
    ReadMediaPlaybackStartTime()
        : ReadAttribute("start-time")
    {
    }

    ~ReadMediaPlaybackStartTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeStartTimeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.StartTime response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback StartTime read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackStartTime : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackStartTime()
        : SubscribeAttribute("start-time")
    {
    }

    ~SubscribeAttributeMediaPlaybackStartTime() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStartTimeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.StartTime response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Duration
 */
class ReadMediaPlaybackDuration : public ReadAttribute {
public:
    ReadMediaPlaybackDuration()
        : ReadAttribute("duration")
    {
    }

    ~ReadMediaPlaybackDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeDurationWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.Duration response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback Duration read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackDuration : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackDuration()
        : SubscribeAttribute("duration")
    {
    }

    ~SubscribeAttributeMediaPlaybackDuration() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDurationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.Duration response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SampledPosition
 */
class ReadMediaPlaybackSampledPosition : public ReadAttribute {
public:
    ReadMediaPlaybackSampledPosition()
        : ReadAttribute("sampled-position")
    {
    }

    ~ReadMediaPlaybackSampledPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSampledPositionWithCompletion:^(
            MTRMediaPlaybackClusterPlaybackPosition * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.SampledPosition response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback SampledPosition read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackSampledPosition : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackSampledPosition()
        : SubscribeAttribute("sampled-position")
    {
    }

    ~SubscribeAttributeMediaPlaybackSampledPosition() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSampledPositionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRMediaPlaybackClusterPlaybackPosition * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.SampledPosition response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PlaybackSpeed
 */
class ReadMediaPlaybackPlaybackSpeed : public ReadAttribute {
public:
    ReadMediaPlaybackPlaybackSpeed()
        : ReadAttribute("playback-speed")
    {
    }

    ~ReadMediaPlaybackPlaybackSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributePlaybackSpeedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.PlaybackSpeed response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback PlaybackSpeed read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackPlaybackSpeed : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackPlaybackSpeed()
        : SubscribeAttribute("playback-speed")
    {
    }

    ~SubscribeAttributeMediaPlaybackPlaybackSpeed() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePlaybackSpeedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.PlaybackSpeed response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SeekRangeEnd
 */
class ReadMediaPlaybackSeekRangeEnd : public ReadAttribute {
public:
    ReadMediaPlaybackSeekRangeEnd()
        : ReadAttribute("seek-range-end")
    {
    }

    ~ReadMediaPlaybackSeekRangeEnd() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSeekRangeEndWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.SeekRangeEnd response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback SeekRangeEnd read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackSeekRangeEnd : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackSeekRangeEnd()
        : SubscribeAttribute("seek-range-end")
    {
    }

    ~SubscribeAttributeMediaPlaybackSeekRangeEnd() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSeekRangeEndWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.SeekRangeEnd response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SeekRangeStart
 */
class ReadMediaPlaybackSeekRangeStart : public ReadAttribute {
public:
    ReadMediaPlaybackSeekRangeStart()
        : ReadAttribute("seek-range-start")
    {
    }

    ~ReadMediaPlaybackSeekRangeStart() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeSeekRangeStartWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.SeekRangeStart response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback SeekRangeStart read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackSeekRangeStart : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackSeekRangeStart()
        : SubscribeAttribute("seek-range-start")
    {
    }

    ~SubscribeAttributeMediaPlaybackSeekRangeStart() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSeekRangeStartWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.SeekRangeStart response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadMediaPlaybackGeneratedCommandList : public ReadAttribute {
public:
    ReadMediaPlaybackGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadMediaPlaybackGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadMediaPlaybackAcceptedCommandList : public ReadAttribute {
public:
    ReadMediaPlaybackAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadMediaPlaybackAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadMediaPlaybackAttributeList : public ReadAttribute {
public:
    ReadMediaPlaybackAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadMediaPlaybackAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeMediaPlaybackAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadMediaPlaybackFeatureMap : public ReadAttribute {
public:
    ReadMediaPlaybackFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadMediaPlaybackFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeMediaPlaybackFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadMediaPlaybackClusterRevision : public ReadAttribute {
public:
    ReadMediaPlaybackClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadMediaPlaybackClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaPlayback.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaPlayback ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaPlaybackClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeMediaPlaybackClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeMediaPlaybackClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000506) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaPlayback * cluster = [[MTRBaseClusterMediaPlayback alloc] initWithDevice:device
                                                                                         endpointID:@(endpointId)
                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaPlayback.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster MediaInput                                                  | 0x0507 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SelectInput                                                       |   0x00 |
| * ShowInputStatus                                                   |   0x01 |
| * HideInputStatus                                                   |   0x02 |
| * RenameInput                                                       |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * InputList                                                         | 0x0000 |
| * CurrentInput                                                      | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SelectInput
 */
class MediaInputSelectInput : public ClusterCommand {
public:
    MediaInputSelectInput()
        : ClusterCommand("select-input")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRMediaInputClusterSelectInputParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.index = [NSNumber numberWithUnsignedChar:mRequest.index];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster selectInputWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaInput::Commands::SelectInput::Type mRequest;
};

/*
 * Command ShowInputStatus
 */
class MediaInputShowInputStatus : public ClusterCommand {
public:
    MediaInputShowInputStatus()
        : ClusterCommand("show-input-status")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRMediaInputClusterShowInputStatusParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster showInputStatusWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command HideInputStatus
 */
class MediaInputHideInputStatus : public ClusterCommand {
public:
    MediaInputHideInputStatus()
        : ClusterCommand("hide-input-status")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRMediaInputClusterHideInputStatusParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster hideInputStatusWithParams:params
                                    completion:^(NSError * _Nullable error) {
                                        responsesNeeded--;
                                        if (error != nil) {
                                            mError = error;
                                            LogNSError("Error", error);
                                        }
                                        if (responsesNeeded == 0) {
                                            SetCommandExitStatus(mError);
                                        }
                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command RenameInput
 */
class MediaInputRenameInput : public ClusterCommand {
public:
    MediaInputRenameInput()
        : ClusterCommand("rename-input")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        AddArgument("Name", &mRequest.name);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        __auto_type * params = [[MTRMediaInputClusterRenameInputParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.index = [NSNumber numberWithUnsignedChar:mRequest.index];
        params.name = [[NSString alloc] initWithBytes:mRequest.name.data()
                                               length:mRequest.name.size()
                                             encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster renameInputWithParams:params
                                completion:^(NSError * _Nullable error) {
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::MediaInput::Commands::RenameInput::Type mRequest;
};

/*
 * Attribute InputList
 */
class ReadMediaInputInputList : public ReadAttribute {
public:
    ReadMediaInputInputList()
        : ReadAttribute("input-list")
    {
    }

    ~ReadMediaInputInputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeInputListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.InputList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput InputList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputInputList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputInputList()
        : SubscribeAttribute("input-list")
    {
    }

    ~SubscribeAttributeMediaInputInputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInputListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.InputList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentInput
 */
class ReadMediaInputCurrentInput : public ReadAttribute {
public:
    ReadMediaInputCurrentInput()
        : ReadAttribute("current-input")
    {
    }

    ~ReadMediaInputCurrentInput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeCurrentInputWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.CurrentInput response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput CurrentInput read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputCurrentInput : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputCurrentInput()
        : SubscribeAttribute("current-input")
    {
    }

    ~SubscribeAttributeMediaInputCurrentInput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentInputWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.CurrentInput response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadMediaInputGeneratedCommandList : public ReadAttribute {
public:
    ReadMediaInputGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadMediaInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeMediaInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadMediaInputAcceptedCommandList : public ReadAttribute {
public:
    ReadMediaInputAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadMediaInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeMediaInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadMediaInputAttributeList : public ReadAttribute {
public:
    ReadMediaInputAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadMediaInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeMediaInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadMediaInputFeatureMap : public ReadAttribute {
public:
    ReadMediaInputFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadMediaInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeMediaInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadMediaInputClusterRevision : public ReadAttribute {
public:
    ReadMediaInputClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadMediaInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"MediaInput.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("MediaInput ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeMediaInputClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeMediaInputClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeMediaInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000507) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterMediaInput * cluster = [[MTRBaseClusterMediaInput alloc] initWithDevice:device
                                                                                   endpointID:@(endpointId)
                                                                                        queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"MediaInput.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster LowPower                                                    | 0x0508 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Sleep                                                             |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command Sleep
 */
class LowPowerSleep : public ClusterCommand {
public:
    LowPowerSleep()
        : ClusterCommand("sleep")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        __auto_type * params = [[MTRLowPowerClusterSleepParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster sleepWithParams:params
                          completion:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute GeneratedCommandList
 */
class ReadLowPowerGeneratedCommandList : public ReadAttribute {
public:
    ReadLowPowerGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadLowPowerGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeLowPowerGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadLowPowerAcceptedCommandList : public ReadAttribute {
public:
    ReadLowPowerAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadLowPowerAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeLowPowerAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadLowPowerAttributeList : public ReadAttribute {
public:
    ReadLowPowerAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadLowPowerAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeLowPowerAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadLowPowerFeatureMap : public ReadAttribute {
public:
    ReadLowPowerFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadLowPowerFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeLowPowerFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadLowPowerClusterRevision : public ReadAttribute {
public:
    ReadLowPowerClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadLowPowerClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"LowPower.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("LowPower ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeLowPowerClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeLowPowerClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeLowPowerClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000508) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterLowPower * cluster = [[MTRBaseClusterLowPower alloc] initWithDevice:device
                                                                               endpointID:@(endpointId)
                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"LowPower.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster KeypadInput                                                 | 0x0509 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SendKey                                                           |   0x00 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SendKey
 */
class KeypadInputSendKey : public ClusterCommand {
public:
    KeypadInputSendKey()
        : ClusterCommand("send-key")
    {
        AddArgument("KeyCode", 0, UINT8_MAX, &mRequest.keyCode);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRKeypadInputClusterSendKeyParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.keyCode = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.keyCode)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster sendKeyWithParams:params
                            completion:^(MTRKeypadInputClusterSendKeyResponseParams * _Nullable values, NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::KeypadInput::Commands::SendKey::Type mRequest;
};

/*
 * Attribute GeneratedCommandList
 */
class ReadKeypadInputGeneratedCommandList : public ReadAttribute {
public:
    ReadKeypadInputGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadKeypadInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeKeypadInputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadKeypadInputAcceptedCommandList : public ReadAttribute {
public:
    ReadKeypadInputAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadKeypadInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeKeypadInputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadKeypadInputAttributeList : public ReadAttribute {
public:
    ReadKeypadInputAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadKeypadInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeKeypadInputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadKeypadInputFeatureMap : public ReadAttribute {
public:
    ReadKeypadInputFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadKeypadInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeKeypadInputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadKeypadInputClusterRevision : public ReadAttribute {
public:
    ReadKeypadInputClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadKeypadInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"KeypadInput.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("KeypadInput ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeKeypadInputClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeKeypadInputClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeKeypadInputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000509) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterKeypadInput * cluster = [[MTRBaseClusterKeypadInput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"KeypadInput.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ContentLauncher                                             | 0x050A |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * LaunchContent                                                     |   0x00 |
| * LaunchURL                                                         |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * AcceptHeader                                                      | 0x0000 |
| * SupportedStreamingProtocols                                       | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command LaunchContent
 */
class ContentLauncherLaunchContent : public ClusterCommand {
public:
    ContentLauncherLaunchContent()
        : ClusterCommand("launch-content")
        , mComplex_Search(&mRequest.search)
    {
        AddArgument("Search", &mComplex_Search);
        AddArgument("AutoPlay", 0, 1, &mRequest.autoPlay);
        AddArgument("Data", &mRequest.data);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRContentLauncherClusterLaunchContentParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.search = [MTRContentLauncherClusterContentSearch new];
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.search.parameterList) {
                MTRContentLauncherClusterParameter * newElement_1;
                newElement_1 = [MTRContentLauncherClusterParameter new];
                newElement_1.type = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1.type)];
                newElement_1.value = [[NSString alloc] initWithBytes:entry_1.value.data()
                                                              length:entry_1.value.size()
                                                            encoding:NSUTF8StringEncoding];
                if (entry_1.externalIDList.HasValue()) {
                    { // Scope for our temporary variables
                        auto * array_4 = [NSMutableArray new];
                        for (auto & entry_4 : entry_1.externalIDList.Value()) {
                            MTRContentLauncherClusterAdditionalInfo * newElement_4;
                            newElement_4 = [MTRContentLauncherClusterAdditionalInfo new];
                            newElement_4.name = [[NSString alloc] initWithBytes:entry_4.name.data()
                                                                         length:entry_4.name.size()
                                                                       encoding:NSUTF8StringEncoding];
                            newElement_4.value = [[NSString alloc] initWithBytes:entry_4.value.data()
                                                                          length:entry_4.value.size()
                                                                        encoding:NSUTF8StringEncoding];
                            [array_4 addObject:newElement_4];
                        }
                        newElement_1.externalIDList = array_4;
                    }
                } else {
                    newElement_1.externalIDList = nil;
                }
                [array_1 addObject:newElement_1];
            }
            params.search.parameterList = array_1;
        }
        params.autoPlay = [NSNumber numberWithBool:mRequest.autoPlay];
        if (mRequest.data.HasValue()) {
            params.data = [[NSString alloc] initWithBytes:mRequest.data.Value().data()
                                                   length:mRequest.data.Value().size()
                                                 encoding:NSUTF8StringEncoding];
        } else {
            params.data = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster launchContentWithParams:params
                                  completion:^(
                                      MTRContentLauncherClusterLaunchResponseParams * _Nullable values, NSError * _Nullable error) {
                                      NSLog(@"Values: %@", values);
                                      responsesNeeded--;
                                      if (error != nil) {
                                          mError = error;
                                          LogNSError("Error", error);
                                      }
                                      if (responsesNeeded == 0) {
                                          SetCommandExitStatus(mError);
                                      }
                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ContentLauncher::Commands::LaunchContent::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ContentLauncher::Structs::ContentSearch::Type> mComplex_Search;
};

/*
 * Command LaunchURL
 */
class ContentLauncherLaunchURL : public ClusterCommand {
public:
    ContentLauncherLaunchURL()
        : ClusterCommand("launch-url")
        , mComplex_BrandingInformation(&mRequest.brandingInformation)
    {
        AddArgument("ContentURL", &mRequest.contentURL);
        AddArgument("DisplayString", &mRequest.displayString);
        AddArgument("BrandingInformation", &mComplex_BrandingInformation);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        __auto_type * params = [[MTRContentLauncherClusterLaunchURLParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.contentURL = [[NSString alloc] initWithBytes:mRequest.contentURL.data()
                                                     length:mRequest.contentURL.size()
                                                   encoding:NSUTF8StringEncoding];
        if (mRequest.displayString.HasValue()) {
            params.displayString = [[NSString alloc] initWithBytes:mRequest.displayString.Value().data()
                                                            length:mRequest.displayString.Value().size()
                                                          encoding:NSUTF8StringEncoding];
        } else {
            params.displayString = nil;
        }
        if (mRequest.brandingInformation.HasValue()) {
            params.brandingInformation = [MTRContentLauncherClusterBrandingInformation new];
            params.brandingInformation.providerName =
                [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().providerName.data()
                                         length:mRequest.brandingInformation.Value().providerName.size()
                                       encoding:NSUTF8StringEncoding];
            if (mRequest.brandingInformation.Value().background.HasValue()) {
                params.brandingInformation.background = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().background.Value().imageUrl.HasValue()) {
                    params.brandingInformation.background.imageUrl = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().background.Value().imageUrl.Value().data()
                               length:mRequest.brandingInformation.Value().background.Value().imageUrl.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.background.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().background.Value().color.HasValue()) {
                    params.brandingInformation.background.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().background.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().background.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.background.color = nil;
                }
                if (mRequest.brandingInformation.Value().background.Value().size.HasValue()) {
                    params.brandingInformation.background.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.background.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().background.Value().size.Value().width];
                    params.brandingInformation.background.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().background.Value().size.Value().height];
                    params.brandingInformation.background.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().background.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.background.size = nil;
                }
            } else {
                params.brandingInformation.background = nil;
            }
            if (mRequest.brandingInformation.Value().logo.HasValue()) {
                params.brandingInformation.logo = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().logo.Value().imageUrl.HasValue()) {
                    params.brandingInformation.logo.imageUrl =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().logo.Value().imageUrl.Value().data()
                                                 length:mRequest.brandingInformation.Value().logo.Value().imageUrl.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.logo.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().logo.Value().color.HasValue()) {
                    params.brandingInformation.logo.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().logo.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().logo.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.logo.color = nil;
                }
                if (mRequest.brandingInformation.Value().logo.Value().size.HasValue()) {
                    params.brandingInformation.logo.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.logo.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().logo.Value().size.Value().width];
                    params.brandingInformation.logo.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().logo.Value().size.Value().height];
                    params.brandingInformation.logo.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().logo.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.logo.size = nil;
                }
            } else {
                params.brandingInformation.logo = nil;
            }
            if (mRequest.brandingInformation.Value().progressBar.HasValue()) {
                params.brandingInformation.progressBar = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().progressBar.Value().imageUrl.HasValue()) {
                    params.brandingInformation.progressBar.imageUrl = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().progressBar.Value().imageUrl.Value().data()
                               length:mRequest.brandingInformation.Value().progressBar.Value().imageUrl.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.progressBar.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().progressBar.Value().color.HasValue()) {
                    params.brandingInformation.progressBar.color = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().progressBar.Value().color.Value().data()
                               length:mRequest.brandingInformation.Value().progressBar.Value().color.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.progressBar.color = nil;
                }
                if (mRequest.brandingInformation.Value().progressBar.Value().size.HasValue()) {
                    params.brandingInformation.progressBar.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.progressBar.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().progressBar.Value().size.Value().width];
                    params.brandingInformation.progressBar.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().progressBar.Value().size.Value().height];
                    params.brandingInformation.progressBar.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().progressBar.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.progressBar.size = nil;
                }
            } else {
                params.brandingInformation.progressBar = nil;
            }
            if (mRequest.brandingInformation.Value().splash.HasValue()) {
                params.brandingInformation.splash = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().splash.Value().imageUrl.HasValue()) {
                    params.brandingInformation.splash.imageUrl =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().splash.Value().imageUrl.Value().data()
                                                 length:mRequest.brandingInformation.Value().splash.Value().imageUrl.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.splash.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().splash.Value().color.HasValue()) {
                    params.brandingInformation.splash.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().splash.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().splash.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.splash.color = nil;
                }
                if (mRequest.brandingInformation.Value().splash.Value().size.HasValue()) {
                    params.brandingInformation.splash.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.splash.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().splash.Value().size.Value().width];
                    params.brandingInformation.splash.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().splash.Value().size.Value().height];
                    params.brandingInformation.splash.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().splash.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.splash.size = nil;
                }
            } else {
                params.brandingInformation.splash = nil;
            }
            if (mRequest.brandingInformation.Value().waterMark.HasValue()) {
                params.brandingInformation.waterMark = [MTRContentLauncherClusterStyleInformation new];
                if (mRequest.brandingInformation.Value().waterMark.Value().imageUrl.HasValue()) {
                    params.brandingInformation.waterMark.imageUrl = [[NSString alloc]
                        initWithBytes:mRequest.brandingInformation.Value().waterMark.Value().imageUrl.Value().data()
                               length:mRequest.brandingInformation.Value().waterMark.Value().imageUrl.Value().size()
                             encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.waterMark.imageUrl = nil;
                }
                if (mRequest.brandingInformation.Value().waterMark.Value().color.HasValue()) {
                    params.brandingInformation.waterMark.color =
                        [[NSString alloc] initWithBytes:mRequest.brandingInformation.Value().waterMark.Value().color.Value().data()
                                                 length:mRequest.brandingInformation.Value().waterMark.Value().color.Value().size()
                                               encoding:NSUTF8StringEncoding];
                } else {
                    params.brandingInformation.waterMark.color = nil;
                }
                if (mRequest.brandingInformation.Value().waterMark.Value().size.HasValue()) {
                    params.brandingInformation.waterMark.size = [MTRContentLauncherClusterDimension new];
                    params.brandingInformation.waterMark.size.width =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().waterMark.Value().size.Value().width];
                    params.brandingInformation.waterMark.size.height =
                        [NSNumber numberWithDouble:mRequest.brandingInformation.Value().waterMark.Value().size.Value().height];
                    params.brandingInformation.waterMark.size.metric = [NSNumber
                        numberWithUnsignedChar:chip::to_underlying(
                                                   mRequest.brandingInformation.Value().waterMark.Value().size.Value().metric)];
                } else {
                    params.brandingInformation.waterMark.size = nil;
                }
            } else {
                params.brandingInformation.waterMark = nil;
            }
        } else {
            params.brandingInformation = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                launchURLWithParams:params
                         completion:^(MTRContentLauncherClusterLaunchResponseParams * _Nullable values, NSError * _Nullable error) {
                             NSLog(@"Values: %@", values);
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ContentLauncher::Commands::LaunchURL::Type mRequest;
    TypedComplexArgument<chip::Optional<chip::app::Clusters::ContentLauncher::Structs::BrandingInformation::Type>>
        mComplex_BrandingInformation;
};

/*
 * Attribute AcceptHeader
 */
class ReadContentLauncherAcceptHeader : public ReadAttribute {
public:
    ReadContentLauncherAcceptHeader()
        : ReadAttribute("accept-header")
    {
    }

    ~ReadContentLauncherAcceptHeader() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptHeaderWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.AcceptHeader response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher AcceptHeader read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherAcceptHeader : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherAcceptHeader()
        : SubscribeAttribute("accept-header")
    {
    }

    ~SubscribeAttributeContentLauncherAcceptHeader() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptHeaderWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.AcceptHeader response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute SupportedStreamingProtocols
 */
class ReadContentLauncherSupportedStreamingProtocols : public ReadAttribute {
public:
    ReadContentLauncherSupportedStreamingProtocols()
        : ReadAttribute("supported-streaming-protocols")
    {
    }

    ~ReadContentLauncherSupportedStreamingProtocols() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeSupportedStreamingProtocolsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.SupportedStreamingProtocols response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher SupportedStreamingProtocols read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteContentLauncherSupportedStreamingProtocols : public WriteAttribute {
public:
    WriteContentLauncherSupportedStreamingProtocols()
        : WriteAttribute("supported-streaming-protocols")
    {
        AddArgument("attr-name", "supported-streaming-protocols");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteContentLauncherSupportedStreamingProtocols() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster
            writeAttributeSupportedStreamingProtocolsWithValue:value
                                                        params:params
                                                    completion:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError(
                                                                "ContentLauncher SupportedStreamingProtocols write Error", error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeContentLauncherSupportedStreamingProtocols : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherSupportedStreamingProtocols()
        : SubscribeAttribute("supported-streaming-protocols")
    {
    }

    ~SubscribeAttributeContentLauncherSupportedStreamingProtocols() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeSupportedStreamingProtocolsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.SupportedStreamingProtocols response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadContentLauncherGeneratedCommandList : public ReadAttribute {
public:
    ReadContentLauncherGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadContentLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeContentLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadContentLauncherAcceptedCommandList : public ReadAttribute {
public:
    ReadContentLauncherAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadContentLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeContentLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadContentLauncherAttributeList : public ReadAttribute {
public:
    ReadContentLauncherAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadContentLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeContentLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadContentLauncherFeatureMap : public ReadAttribute {
public:
    ReadContentLauncherFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadContentLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeContentLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadContentLauncherClusterRevision : public ReadAttribute {
public:
    ReadContentLauncherClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadContentLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ContentLauncher.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ContentLauncher ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeContentLauncherClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeContentLauncherClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeContentLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050A) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterContentLauncher * cluster = [[MTRBaseClusterContentLauncher alloc] initWithDevice:device
                                                                                             endpointID:@(endpointId)
                                                                                                  queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ContentLauncher.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AudioOutput                                                 | 0x050B |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * SelectOutput                                                      |   0x00 |
| * RenameOutput                                                      |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * OutputList                                                        | 0x0000 |
| * CurrentOutput                                                     | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command SelectOutput
 */
class AudioOutputSelectOutput : public ClusterCommand {
public:
    AudioOutputSelectOutput()
        : ClusterCommand("select-output")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRAudioOutputClusterSelectOutputParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.index = [NSNumber numberWithUnsignedChar:mRequest.index];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster selectOutputWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AudioOutput::Commands::SelectOutput::Type mRequest;
};

/*
 * Command RenameOutput
 */
class AudioOutputRenameOutput : public ClusterCommand {
public:
    AudioOutputRenameOutput()
        : ClusterCommand("rename-output")
    {
        AddArgument("Index", 0, UINT8_MAX, &mRequest.index);
        AddArgument("Name", &mRequest.name);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRAudioOutputClusterRenameOutputParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.index = [NSNumber numberWithUnsignedChar:mRequest.index];
        params.name = [[NSString alloc] initWithBytes:mRequest.name.data()
                                               length:mRequest.name.size()
                                             encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster renameOutputWithParams:params
                                 completion:^(NSError * _Nullable error) {
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AudioOutput::Commands::RenameOutput::Type mRequest;
};

/*
 * Attribute OutputList
 */
class ReadAudioOutputOutputList : public ReadAttribute {
public:
    ReadAudioOutputOutputList()
        : ReadAttribute("output-list")
    {
    }

    ~ReadAudioOutputOutputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeOutputListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.OutputList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput OutputList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputOutputList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputOutputList()
        : SubscribeAttribute("output-list")
    {
    }

    ~SubscribeAttributeAudioOutputOutputList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOutputListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.OutputList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentOutput
 */
class ReadAudioOutputCurrentOutput : public ReadAttribute {
public:
    ReadAudioOutputCurrentOutput()
        : ReadAttribute("current-output")
    {
    }

    ~ReadAudioOutputCurrentOutput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentOutputWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.CurrentOutput response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput CurrentOutput read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputCurrentOutput : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputCurrentOutput()
        : SubscribeAttribute("current-output")
    {
    }

    ~SubscribeAttributeAudioOutputCurrentOutput() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentOutputWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.CurrentOutput response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAudioOutputGeneratedCommandList : public ReadAttribute {
public:
    ReadAudioOutputGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAudioOutputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAudioOutputGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAudioOutputAcceptedCommandList : public ReadAttribute {
public:
    ReadAudioOutputAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAudioOutputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAudioOutputAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAudioOutputAttributeList : public ReadAttribute {
public:
    ReadAudioOutputAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAudioOutputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAudioOutputAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAudioOutputFeatureMap : public ReadAttribute {
public:
    ReadAudioOutputFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAudioOutputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAudioOutputFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAudioOutputClusterRevision : public ReadAttribute {
public:
    ReadAudioOutputClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAudioOutputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AudioOutput.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AudioOutput ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAudioOutputClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAudioOutputClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAudioOutputClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050B) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAudioOutput * cluster = [[MTRBaseClusterAudioOutput alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AudioOutput.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ApplicationLauncher                                         | 0x050C |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * LaunchApp                                                         |   0x00 |
| * StopApp                                                           |   0x01 |
| * HideApp                                                           |   0x02 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * CatalogList                                                       | 0x0000 |
| * CurrentApp                                                        | 0x0001 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command LaunchApp
 */
class ApplicationLauncherLaunchApp : public ClusterCommand {
public:
    ApplicationLauncherLaunchApp()
        : ClusterCommand("launch-app")
        , mComplex_Application(&mRequest.application)
    {
        AddArgument("Application", &mComplex_Application);
        AddArgument("Data", &mRequest.data);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterLaunchAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.application = [MTRApplicationLauncherClusterApplication new];
        params.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mRequest.application.catalogVendorId];
        params.application.applicationId = [[NSString alloc] initWithBytes:mRequest.application.applicationId.data()
                                                                    length:mRequest.application.applicationId.size()
                                                                  encoding:NSUTF8StringEncoding];
        if (mRequest.data.HasValue()) {
            params.data = [NSData dataWithBytes:mRequest.data.Value().data() length:mRequest.data.Value().size()];
        } else {
            params.data = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster launchAppWithParams:params
                              completion:^(MTRApplicationLauncherClusterLauncherResponseParams * _Nullable values,
                                  NSError * _Nullable error) {
                                  NSLog(@"Values: %@", values);
                                  responsesNeeded--;
                                  if (error != nil) {
                                      mError = error;
                                      LogNSError("Error", error);
                                  }
                                  if (responsesNeeded == 0) {
                                      SetCommandExitStatus(mError);
                                  }
                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ApplicationLauncher::Commands::LaunchApp::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ApplicationLauncher::Structs::Application::Type> mComplex_Application;
};

/*
 * Command StopApp
 */
class ApplicationLauncherStopApp : public ClusterCommand {
public:
    ApplicationLauncherStopApp()
        : ClusterCommand("stop-app")
        , mComplex_Application(&mRequest.application)
    {
        AddArgument("Application", &mComplex_Application);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterStopAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.application = [MTRApplicationLauncherClusterApplication new];
        params.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mRequest.application.catalogVendorId];
        params.application.applicationId = [[NSString alloc] initWithBytes:mRequest.application.applicationId.data()
                                                                    length:mRequest.application.applicationId.size()
                                                                  encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster stopAppWithParams:params
                            completion:^(
                                MTRApplicationLauncherClusterLauncherResponseParams * _Nullable values, NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ApplicationLauncher::Commands::StopApp::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ApplicationLauncher::Structs::Application::Type> mComplex_Application;
};

/*
 * Command HideApp
 */
class ApplicationLauncherHideApp : public ClusterCommand {
public:
    ApplicationLauncherHideApp()
        : ClusterCommand("hide-app")
        , mComplex_Application(&mRequest.application)
    {
        AddArgument("Application", &mComplex_Application);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRApplicationLauncherClusterHideAppParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.application = [MTRApplicationLauncherClusterApplication new];
        params.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mRequest.application.catalogVendorId];
        params.application.applicationId = [[NSString alloc] initWithBytes:mRequest.application.applicationId.data()
                                                                    length:mRequest.application.applicationId.size()
                                                                  encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster hideAppWithParams:params
                            completion:^(
                                MTRApplicationLauncherClusterLauncherResponseParams * _Nullable values, NSError * _Nullable error) {
                                NSLog(@"Values: %@", values);
                                responsesNeeded--;
                                if (error != nil) {
                                    mError = error;
                                    LogNSError("Error", error);
                                }
                                if (responsesNeeded == 0) {
                                    SetCommandExitStatus(mError);
                                }
                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ApplicationLauncher::Commands::HideApp::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::ApplicationLauncher::Structs::Application::Type> mComplex_Application;
};

/*
 * Attribute CatalogList
 */
class ReadApplicationLauncherCatalogList : public ReadAttribute {
public:
    ReadApplicationLauncherCatalogList()
        : ReadAttribute("catalog-list")
    {
    }

    ~ReadApplicationLauncherCatalogList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCatalogListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.CatalogList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher CatalogList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherCatalogList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherCatalogList()
        : SubscribeAttribute("catalog-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherCatalogList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCatalogListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.CatalogList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentApp
 */
class ReadApplicationLauncherCurrentApp : public ReadAttribute {
public:
    ReadApplicationLauncherCurrentApp()
        : ReadAttribute("current-app")
    {
    }

    ~ReadApplicationLauncherCurrentApp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeCurrentAppWithCompletion:^(
            MTRApplicationLauncherClusterApplicationEP * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.CurrentApp response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher CurrentApp read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteApplicationLauncherCurrentApp : public WriteAttribute {
public:
    WriteApplicationLauncherCurrentApp()
        : WriteAttribute("current-app")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "current-app");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteApplicationLauncherCurrentApp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRApplicationLauncherClusterApplicationEP * _Nullable value;
        if (mValue.IsNull()) {
            value = nil;
        } else {
            value = [MTRApplicationLauncherClusterApplicationEP new];
            value.application = [MTRApplicationLauncherClusterApplication new];
            value.application.catalogVendorId = [NSNumber numberWithUnsignedShort:mValue.Value().application.catalogVendorId];
            value.application.applicationId = [[NSString alloc] initWithBytes:mValue.Value().application.applicationId.data()
                                                                       length:mValue.Value().application.applicationId.size()
                                                                     encoding:NSUTF8StringEncoding];
            if (mValue.Value().endpoint.HasValue()) {
                value.endpoint = [NSNumber numberWithUnsignedShort:mValue.Value().endpoint.Value()];
            } else {
                value.endpoint = nil;
            }
        }

        [cluster writeAttributeCurrentAppWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("ApplicationLauncher CurrentApp write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::Nullable<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationEP::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::ApplicationLauncher::Structs::ApplicationEP::Type>>
        mComplex;
};

class SubscribeAttributeApplicationLauncherCurrentApp : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherCurrentApp()
        : SubscribeAttribute("current-app")
    {
    }

    ~SubscribeAttributeApplicationLauncherCurrentApp() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentAppWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRApplicationLauncherClusterApplicationEP * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.CurrentApp response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadApplicationLauncherGeneratedCommandList : public ReadAttribute {
public:
    ReadApplicationLauncherGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadApplicationLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadApplicationLauncherAcceptedCommandList : public ReadAttribute {
public:
    ReadApplicationLauncherAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadApplicationLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadApplicationLauncherAttributeList : public ReadAttribute {
public:
    ReadApplicationLauncherAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadApplicationLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeApplicationLauncherAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadApplicationLauncherFeatureMap : public ReadAttribute {
public:
    ReadApplicationLauncherFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadApplicationLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeApplicationLauncherFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadApplicationLauncherClusterRevision : public ReadAttribute {
public:
    ReadApplicationLauncherClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadApplicationLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationLauncher.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationLauncher ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationLauncherClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationLauncherClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeApplicationLauncherClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050C) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationLauncher * cluster = [[MTRBaseClusterApplicationLauncher alloc] initWithDevice:device
                                                                                                     endpointID:@(endpointId)
                                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationLauncher.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ApplicationBasic                                            | 0x050D |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * VendorName                                                        | 0x0000 |
| * VendorID                                                          | 0x0001 |
| * ApplicationName                                                   | 0x0002 |
| * ProductID                                                         | 0x0003 |
| * Application                                                       | 0x0004 |
| * Status                                                            | 0x0005 |
| * ApplicationVersion                                                | 0x0006 |
| * AllowedVendorList                                                 | 0x0007 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Attribute VendorName
 */
class ReadApplicationBasicVendorName : public ReadAttribute {
public:
    ReadApplicationBasicVendorName()
        : ReadAttribute("vendor-name")
    {
    }

    ~ReadApplicationBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeVendorNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.VendorName response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic VendorName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicVendorName : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicVendorName()
        : SubscribeAttribute("vendor-name")
    {
    }

    ~SubscribeAttributeApplicationBasicVendorName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.VendorName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorID
 */
class ReadApplicationBasicVendorID : public ReadAttribute {
public:
    ReadApplicationBasicVendorID()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadApplicationBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeVendorIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.VendorID response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic VendorID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicVendorID : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicVendorID()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeApplicationBasicVendorID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.VendorID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApplicationName
 */
class ReadApplicationBasicApplicationName : public ReadAttribute {
public:
    ReadApplicationBasicApplicationName()
        : ReadAttribute("application-name")
    {
    }

    ~ReadApplicationBasicApplicationName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationNameWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ApplicationName response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ApplicationName read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicApplicationName : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicApplicationName()
        : SubscribeAttribute("application-name")
    {
    }

    ~SubscribeAttributeApplicationBasicApplicationName() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApplicationNameWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ApplicationName response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ProductID
 */
class ReadApplicationBasicProductID : public ReadAttribute {
public:
    ReadApplicationBasicProductID()
        : ReadAttribute("product-id")
    {
    }

    ~ReadApplicationBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeProductIDWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ProductID response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ProductID read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicProductID : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicProductID()
        : SubscribeAttribute("product-id")
    {
    }

    ~SubscribeAttributeApplicationBasicProductID() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeProductIDWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ProductID response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Application
 */
class ReadApplicationBasicApplication : public ReadAttribute {
public:
    ReadApplicationBasicApplication()
        : ReadAttribute("application")
    {
    }

    ~ReadApplicationBasicApplication() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationWithCompletion:^(
            MTRApplicationBasicClusterApplicationBasicApplication * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.Application response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic Application read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicApplication : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicApplication()
        : SubscribeAttribute("application")
    {
    }

    ~SubscribeAttributeApplicationBasicApplication() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApplicationWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRApplicationBasicClusterApplicationBasicApplication * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.Application response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Status
 */
class ReadApplicationBasicStatus : public ReadAttribute {
public:
    ReadApplicationBasicStatus()
        : ReadAttribute("status")
    {
    }

    ~ReadApplicationBasicStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeStatusWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.Status response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic Status read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicStatus : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicStatus()
        : SubscribeAttribute("status")
    {
    }

    ~SubscribeAttributeApplicationBasicStatus() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStatusWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.Status response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApplicationVersion
 */
class ReadApplicationBasicApplicationVersion : public ReadAttribute {
public:
    ReadApplicationBasicApplicationVersion()
        : ReadAttribute("application-version")
    {
    }

    ~ReadApplicationBasicApplicationVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeApplicationVersionWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ApplicationVersion response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ApplicationVersion read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicApplicationVersion : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicApplicationVersion()
        : SubscribeAttribute("application-version")
    {
    }

    ~SubscribeAttributeApplicationBasicApplicationVersion() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApplicationVersionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ApplicationVersion response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AllowedVendorList
 */
class ReadApplicationBasicAllowedVendorList : public ReadAttribute {
public:
    ReadApplicationBasicAllowedVendorList()
        : ReadAttribute("allowed-vendor-list")
    {
    }

    ~ReadApplicationBasicAllowedVendorList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAllowedVendorListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.AllowedVendorList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic AllowedVendorList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicAllowedVendorList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicAllowedVendorList()
        : SubscribeAttribute("allowed-vendor-list")
    {
    }

    ~SubscribeAttributeApplicationBasicAllowedVendorList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAllowedVendorListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.AllowedVendorList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadApplicationBasicGeneratedCommandList : public ReadAttribute {
public:
    ReadApplicationBasicGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadApplicationBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeApplicationBasicGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadApplicationBasicAcceptedCommandList : public ReadAttribute {
public:
    ReadApplicationBasicAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadApplicationBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeApplicationBasicAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadApplicationBasicAttributeList : public ReadAttribute {
public:
    ReadApplicationBasicAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadApplicationBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeApplicationBasicAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadApplicationBasicFeatureMap : public ReadAttribute {
public:
    ReadApplicationBasicFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadApplicationBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeApplicationBasicFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadApplicationBasicClusterRevision : public ReadAttribute {
public:
    ReadApplicationBasicClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadApplicationBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ApplicationBasic.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ApplicationBasic ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeApplicationBasicClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeApplicationBasicClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeApplicationBasicClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050D) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterApplicationBasic * cluster = [[MTRBaseClusterApplicationBasic alloc] initWithDevice:device
                                                                                               endpointID:@(endpointId)
                                                                                                    queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ApplicationBasic.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster AccountLogin                                                | 0x050E |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * GetSetupPIN                                                       |   0x00 |
| * Login                                                             |   0x02 |
| * Logout                                                            |   0x03 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command GetSetupPIN
 */
class AccountLoginGetSetupPIN : public ClusterCommand {
public:
    AccountLoginGetSetupPIN()
        : ClusterCommand("get-setup-pin")
    {
        AddArgument("TempAccountIdentifier", &mRequest.tempAccountIdentifier);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRAccountLoginClusterGetSetupPINParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.tempAccountIdentifier = [[NSString alloc] initWithBytes:mRequest.tempAccountIdentifier.data()
                                                                length:mRequest.tempAccountIdentifier.size()
                                                              encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getSetupPINWithParams:params
                                completion:^(
                                    MTRAccountLoginClusterGetSetupPINResponseParams * _Nullable values, NSError * _Nullable error) {
                                    NSLog(@"Values: %@", values);
                                    responsesNeeded--;
                                    if (error != nil) {
                                        mError = error;
                                        LogNSError("Error", error);
                                    }
                                    if (responsesNeeded == 0) {
                                        SetCommandExitStatus(mError);
                                    }
                                }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AccountLogin::Commands::GetSetupPIN::Type mRequest;
};

/*
 * Command Login
 */
class AccountLoginLogin : public ClusterCommand {
public:
    AccountLoginLogin()
        : ClusterCommand("login")
    {
        AddArgument("TempAccountIdentifier", &mRequest.tempAccountIdentifier);
        AddArgument("SetupPIN", &mRequest.setupPIN);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRAccountLoginClusterLoginParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.tempAccountIdentifier = [[NSString alloc] initWithBytes:mRequest.tempAccountIdentifier.data()
                                                                length:mRequest.tempAccountIdentifier.size()
                                                              encoding:NSUTF8StringEncoding];
        params.setupPIN = [[NSString alloc] initWithBytes:mRequest.setupPIN.data()
                                                   length:mRequest.setupPIN.size()
                                                 encoding:NSUTF8StringEncoding];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster loginWithParams:params
                          completion:^(NSError * _Nullable error) {
                              responsesNeeded--;
                              if (error != nil) {
                                  mError = error;
                                  LogNSError("Error", error);
                              }
                              if (responsesNeeded == 0) {
                                  SetCommandExitStatus(mError);
                              }
                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::AccountLogin::Commands::Login::Type mRequest;
};

/*
 * Command Logout
 */
class AccountLoginLogout : public ClusterCommand {
public:
    AccountLoginLogout()
        : ClusterCommand("logout")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        __auto_type * params = [[MTRAccountLoginClusterLogoutParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster logoutWithParams:params
                           completion:^(NSError * _Nullable error) {
                               responsesNeeded--;
                               if (error != nil) {
                                   mError = error;
                                   LogNSError("Error", error);
                               }
                               if (responsesNeeded == 0) {
                                   SetCommandExitStatus(mError);
                               }
                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Attribute GeneratedCommandList
 */
class ReadAccountLoginGeneratedCommandList : public ReadAttribute {
public:
    ReadAccountLoginGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadAccountLoginGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeAccountLoginGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadAccountLoginAcceptedCommandList : public ReadAttribute {
public:
    ReadAccountLoginAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadAccountLoginAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeAccountLoginAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadAccountLoginAttributeList : public ReadAttribute {
public:
    ReadAccountLoginAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadAccountLoginAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeAccountLoginAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadAccountLoginFeatureMap : public ReadAttribute {
public:
    ReadAccountLoginFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadAccountLoginFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeAccountLoginFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadAccountLoginClusterRevision : public ReadAttribute {
public:
    ReadAccountLoginClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadAccountLoginClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"AccountLogin.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("AccountLogin ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeAccountLoginClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeAccountLoginClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeAccountLoginClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x0000050E) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterAccountLogin * cluster = [[MTRBaseClusterAccountLogin alloc] initWithDevice:device
                                                                                       endpointID:@(endpointId)
                                                                                            queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"AccountLogin.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster ElectricalMeasurement                                       | 0x0B04 |
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * GetProfileInfoCommand                                             |   0x00 |
| * GetMeasurementProfileCommand                                      |   0x01 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * MeasurementType                                                   | 0x0000 |
| * DcVoltage                                                         | 0x0100 |
| * DcVoltageMin                                                      | 0x0101 |
| * DcVoltageMax                                                      | 0x0102 |
| * DcCurrent                                                         | 0x0103 |
| * DcCurrentMin                                                      | 0x0104 |
| * DcCurrentMax                                                      | 0x0105 |
| * DcPower                                                           | 0x0106 |
| * DcPowerMin                                                        | 0x0107 |
| * DcPowerMax                                                        | 0x0108 |
| * DcVoltageMultiplier                                               | 0x0200 |
| * DcVoltageDivisor                                                  | 0x0201 |
| * DcCurrentMultiplier                                               | 0x0202 |
| * DcCurrentDivisor                                                  | 0x0203 |
| * DcPowerMultiplier                                                 | 0x0204 |
| * DcPowerDivisor                                                    | 0x0205 |
| * AcFrequency                                                       | 0x0300 |
| * AcFrequencyMin                                                    | 0x0301 |
| * AcFrequencyMax                                                    | 0x0302 |
| * NeutralCurrent                                                    | 0x0303 |
| * TotalActivePower                                                  | 0x0304 |
| * TotalReactivePower                                                | 0x0305 |
| * TotalApparentPower                                                | 0x0306 |
| * Measured1stHarmonicCurrent                                        | 0x0307 |
| * Measured3rdHarmonicCurrent                                        | 0x0308 |
| * Measured5thHarmonicCurrent                                        | 0x0309 |
| * Measured7thHarmonicCurrent                                        | 0x030A |
| * Measured9thHarmonicCurrent                                        | 0x030B |
| * Measured11thHarmonicCurrent                                       | 0x030C |
| * MeasuredPhase1stHarmonicCurrent                                   | 0x030D |
| * MeasuredPhase3rdHarmonicCurrent                                   | 0x030E |
| * MeasuredPhase5thHarmonicCurrent                                   | 0x030F |
| * MeasuredPhase7thHarmonicCurrent                                   | 0x0310 |
| * MeasuredPhase9thHarmonicCurrent                                   | 0x0311 |
| * MeasuredPhase11thHarmonicCurrent                                  | 0x0312 |
| * AcFrequencyMultiplier                                             | 0x0400 |
| * AcFrequencyDivisor                                                | 0x0401 |
| * PowerMultiplier                                                   | 0x0402 |
| * PowerDivisor                                                      | 0x0403 |
| * HarmonicCurrentMultiplier                                         | 0x0404 |
| * PhaseHarmonicCurrentMultiplier                                    | 0x0405 |
| * InstantaneousVoltage                                              | 0x0500 |
| * InstantaneousLineCurrent                                          | 0x0501 |
| * InstantaneousActiveCurrent                                        | 0x0502 |
| * InstantaneousReactiveCurrent                                      | 0x0503 |
| * InstantaneousPower                                                | 0x0504 |
| * RmsVoltage                                                        | 0x0505 |
| * RmsVoltageMin                                                     | 0x0506 |
| * RmsVoltageMax                                                     | 0x0507 |
| * RmsCurrent                                                        | 0x0508 |
| * RmsCurrentMin                                                     | 0x0509 |
| * RmsCurrentMax                                                     | 0x050A |
| * ActivePower                                                       | 0x050B |
| * ActivePowerMin                                                    | 0x050C |
| * ActivePowerMax                                                    | 0x050D |
| * ReactivePower                                                     | 0x050E |
| * ApparentPower                                                     | 0x050F |
| * PowerFactor                                                       | 0x0510 |
| * AverageRmsVoltageMeasurementPeriod                                | 0x0511 |
| * AverageRmsUnderVoltageCounter                                     | 0x0513 |
| * RmsExtremeOverVoltagePeriod                                       | 0x0514 |
| * RmsExtremeUnderVoltagePeriod                                      | 0x0515 |
| * RmsVoltageSagPeriod                                               | 0x0516 |
| * RmsVoltageSwellPeriod                                             | 0x0517 |
| * AcVoltageMultiplier                                               | 0x0600 |
| * AcVoltageDivisor                                                  | 0x0601 |
| * AcCurrentMultiplier                                               | 0x0602 |
| * AcCurrentDivisor                                                  | 0x0603 |
| * AcPowerMultiplier                                                 | 0x0604 |
| * AcPowerDivisor                                                    | 0x0605 |
| * OverloadAlarmsMask                                                | 0x0700 |
| * VoltageOverload                                                   | 0x0701 |
| * CurrentOverload                                                   | 0x0702 |
| * AcOverloadAlarmsMask                                              | 0x0800 |
| * AcVoltageOverload                                                 | 0x0801 |
| * AcCurrentOverload                                                 | 0x0802 |
| * AcActivePowerOverload                                             | 0x0803 |
| * AcReactivePowerOverload                                           | 0x0804 |
| * AverageRmsOverVoltage                                             | 0x0805 |
| * AverageRmsUnderVoltage                                            | 0x0806 |
| * RmsExtremeOverVoltage                                             | 0x0807 |
| * RmsExtremeUnderVoltage                                            | 0x0808 |
| * RmsVoltageSag                                                     | 0x0809 |
| * RmsVoltageSwell                                                   | 0x080A |
| * LineCurrentPhaseB                                                 | 0x0901 |
| * ActiveCurrentPhaseB                                               | 0x0902 |
| * ReactiveCurrentPhaseB                                             | 0x0903 |
| * RmsVoltagePhaseB                                                  | 0x0905 |
| * RmsVoltageMinPhaseB                                               | 0x0906 |
| * RmsVoltageMaxPhaseB                                               | 0x0907 |
| * RmsCurrentPhaseB                                                  | 0x0908 |
| * RmsCurrentMinPhaseB                                               | 0x0909 |
| * RmsCurrentMaxPhaseB                                               | 0x090A |
| * ActivePowerPhaseB                                                 | 0x090B |
| * ActivePowerMinPhaseB                                              | 0x090C |
| * ActivePowerMaxPhaseB                                              | 0x090D |
| * ReactivePowerPhaseB                                               | 0x090E |
| * ApparentPowerPhaseB                                               | 0x090F |
| * PowerFactorPhaseB                                                 | 0x0910 |
| * AverageRmsVoltageMeasurementPeriodPhaseB                          | 0x0911 |
| * AverageRmsOverVoltageCounterPhaseB                                | 0x0912 |
| * AverageRmsUnderVoltageCounterPhaseB                               | 0x0913 |
| * RmsExtremeOverVoltagePeriodPhaseB                                 | 0x0914 |
| * RmsExtremeUnderVoltagePeriodPhaseB                                | 0x0915 |
| * RmsVoltageSagPeriodPhaseB                                         | 0x0916 |
| * RmsVoltageSwellPeriodPhaseB                                       | 0x0917 |
| * LineCurrentPhaseC                                                 | 0x0A01 |
| * ActiveCurrentPhaseC                                               | 0x0A02 |
| * ReactiveCurrentPhaseC                                             | 0x0A03 |
| * RmsVoltagePhaseC                                                  | 0x0A05 |
| * RmsVoltageMinPhaseC                                               | 0x0A06 |
| * RmsVoltageMaxPhaseC                                               | 0x0A07 |
| * RmsCurrentPhaseC                                                  | 0x0A08 |
| * RmsCurrentMinPhaseC                                               | 0x0A09 |
| * RmsCurrentMaxPhaseC                                               | 0x0A0A |
| * ActivePowerPhaseC                                                 | 0x0A0B |
| * ActivePowerMinPhaseC                                              | 0x0A0C |
| * ActivePowerMaxPhaseC                                              | 0x0A0D |
| * ReactivePowerPhaseC                                               | 0x0A0E |
| * ApparentPowerPhaseC                                               | 0x0A0F |
| * PowerFactorPhaseC                                                 | 0x0A10 |
| * AverageRmsVoltageMeasurementPeriodPhaseC                          | 0x0A11 |
| * AverageRmsOverVoltageCounterPhaseC                                | 0x0A12 |
| * AverageRmsUnderVoltageCounterPhaseC                               | 0x0A13 |
| * RmsExtremeOverVoltagePeriodPhaseC                                 | 0x0A14 |
| * RmsExtremeUnderVoltagePeriodPhaseC                                | 0x0A15 |
| * RmsVoltageSagPeriodPhaseC                                         | 0x0A16 |
| * RmsVoltageSwellPeriodPhaseC                                       | 0x0A17 |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
\*----------------------------------------------------------------------------*/

/*
 * Command GetProfileInfoCommand
 */
class ElectricalMeasurementGetProfileInfoCommand : public ClusterCommand {
public:
    ElectricalMeasurementGetProfileInfoCommand()
        : ClusterCommand("get-profile-info-command")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRElectricalMeasurementClusterGetProfileInfoCommandParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getProfileInfoCommandWithParams:params
                                          completion:^(NSError * _Nullable error) {
                                              responsesNeeded--;
                                              if (error != nil) {
                                                  mError = error;
                                                  LogNSError("Error", error);
                                              }
                                              if (responsesNeeded == 0) {
                                                  SetCommandExitStatus(mError);
                                              }
                                          }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command GetMeasurementProfileCommand
 */
class ElectricalMeasurementGetMeasurementProfileCommand : public ClusterCommand {
public:
    ElectricalMeasurementGetMeasurementProfileCommand()
        : ClusterCommand("get-measurement-profile-command")
    {
        AddArgument("AttributeId", 0, UINT16_MAX, &mRequest.attributeId);
        AddArgument("StartTime", 0, UINT32_MAX, &mRequest.startTime);
        AddArgument("NumberOfIntervals", 0, UINT8_MAX, &mRequest.numberOfIntervals);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        __auto_type * params = [[MTRElectricalMeasurementClusterGetMeasurementProfileCommandParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.attributeId = [NSNumber numberWithUnsignedShort:mRequest.attributeId];
        params.startTime = [NSNumber numberWithUnsignedInt:mRequest.startTime];
        params.numberOfIntervals = [NSNumber numberWithUnsignedChar:mRequest.numberOfIntervals];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster getMeasurementProfileCommandWithParams:params
                                                 completion:^(NSError * _Nullable error) {
                                                     responsesNeeded--;
                                                     if (error != nil) {
                                                         mError = error;
                                                         LogNSError("Error", error);
                                                     }
                                                     if (responsesNeeded == 0) {
                                                         SetCommandExitStatus(mError);
                                                     }
                                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::ElectricalMeasurement::Commands::GetMeasurementProfileCommand::Type mRequest;
};

/*
 * Attribute MeasurementType
 */
class ReadElectricalMeasurementMeasurementType : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasurementType()
        : ReadAttribute("measurement-type")
    {
    }

    ~ReadElectricalMeasurementMeasurementType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasurementTypeWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.MeasurementType response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement MeasurementType read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasurementType : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasurementType()
        : SubscribeAttribute("measurement-type")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasurementType() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasurementTypeWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasurementType response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltage
 */
class ReadElectricalMeasurementDcVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltage()
        : ReadAttribute("dc-voltage")
    {
    }

    ~ReadElectricalMeasurementDcVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000100) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltage()
        : SubscribeAttribute("dc-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000100) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageMin
 */
class ReadElectricalMeasurementDcVoltageMin : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageMin()
        : ReadAttribute("dc-voltage-min")
    {
    }

    ~ReadElectricalMeasurementDcVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000101) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageMin()
        : SubscribeAttribute("dc-voltage-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000101) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcVoltageMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageMax
 */
class ReadElectricalMeasurementDcVoltageMax : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageMax()
        : ReadAttribute("dc-voltage-max")
    {
    }

    ~ReadElectricalMeasurementDcVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000102) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageMax()
        : SubscribeAttribute("dc-voltage-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000102) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcVoltageMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrent
 */
class ReadElectricalMeasurementDcCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrent()
        : ReadAttribute("dc-current")
    {
    }

    ~ReadElectricalMeasurementDcCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000103) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrent()
        : SubscribeAttribute("dc-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000103) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentMin
 */
class ReadElectricalMeasurementDcCurrentMin : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentMin()
        : ReadAttribute("dc-current-min")
    {
    }

    ~ReadElectricalMeasurementDcCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000104) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentMin()
        : SubscribeAttribute("dc-current-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000104) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcCurrentMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentMax
 */
class ReadElectricalMeasurementDcCurrentMax : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentMax()
        : ReadAttribute("dc-current-max")
    {
    }

    ~ReadElectricalMeasurementDcCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000105) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentMax()
        : SubscribeAttribute("dc-current-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000105) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcCurrentMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPower
 */
class ReadElectricalMeasurementDcPower : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPower()
        : ReadAttribute("dc-power")
    {
    }

    ~ReadElectricalMeasurementDcPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000106) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPower()
        : SubscribeAttribute("dc-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000106) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcPowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerMin
 */
class ReadElectricalMeasurementDcPowerMin : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerMin()
        : ReadAttribute("dc-power-min")
    {
    }

    ~ReadElectricalMeasurementDcPowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000107) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerMin()
        : SubscribeAttribute("dc-power-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000107) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcPowerMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerMax
 */
class ReadElectricalMeasurementDcPowerMax : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerMax()
        : ReadAttribute("dc-power-max")
    {
    }

    ~ReadElectricalMeasurementDcPowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000108) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerMax()
        : SubscribeAttribute("dc-power-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000108) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcPowerMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageMultiplier
 */
class ReadElectricalMeasurementDcVoltageMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageMultiplier()
        : ReadAttribute("dc-voltage-multiplier")
    {
    }

    ~ReadElectricalMeasurementDcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000200) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageMultiplier()
        : SubscribeAttribute("dc-voltage-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000200) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcVoltageMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcVoltageDivisor
 */
class ReadElectricalMeasurementDcVoltageDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementDcVoltageDivisor()
        : ReadAttribute("dc-voltage-divisor")
    {
    }

    ~ReadElectricalMeasurementDcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000201) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcVoltageDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcVoltageDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcVoltageDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcVoltageDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcVoltageDivisor()
        : SubscribeAttribute("dc-voltage-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000201) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcVoltageDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcVoltageDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentMultiplier
 */
class ReadElectricalMeasurementDcCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentMultiplier()
        : ReadAttribute("dc-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementDcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000202) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentMultiplier()
        : SubscribeAttribute("dc-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000202) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcCurrentMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcCurrentDivisor
 */
class ReadElectricalMeasurementDcCurrentDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementDcCurrentDivisor()
        : ReadAttribute("dc-current-divisor")
    {
    }

    ~ReadElectricalMeasurementDcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000203) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcCurrentDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcCurrentDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcCurrentDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcCurrentDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcCurrentDivisor()
        : SubscribeAttribute("dc-current-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000203) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcCurrentDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcCurrentDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerMultiplier
 */
class ReadElectricalMeasurementDcPowerMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerMultiplier()
        : ReadAttribute("dc-power-multiplier")
    {
    }

    ~ReadElectricalMeasurementDcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000204) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerMultiplier()
        : SubscribeAttribute("dc-power-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000204) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcPowerMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute DcPowerDivisor
 */
class ReadElectricalMeasurementDcPowerDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementDcPowerDivisor()
        : ReadAttribute("dc-power-divisor")
    {
    }

    ~ReadElectricalMeasurementDcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000205) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeDcPowerDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.DcPowerDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement DcPowerDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementDcPowerDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementDcPowerDivisor()
        : SubscribeAttribute("dc-power-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementDcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000205) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeDcPowerDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.DcPowerDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequency
 */
class ReadElectricalMeasurementAcFrequency : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequency()
        : ReadAttribute("ac-frequency")
    {
    }

    ~ReadElectricalMeasurementAcFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000300) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequency response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequency read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequency : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequency()
        : SubscribeAttribute("ac-frequency")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequency() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000300) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcFrequencyWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequency response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyMin
 */
class ReadElectricalMeasurementAcFrequencyMin : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyMin()
        : ReadAttribute("ac-frequency-min")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000301) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyMin()
        : SubscribeAttribute("ac-frequency-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000301) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcFrequencyMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyMax
 */
class ReadElectricalMeasurementAcFrequencyMax : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyMax()
        : ReadAttribute("ac-frequency-max")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000302) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyMax()
        : SubscribeAttribute("ac-frequency-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000302) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcFrequencyMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NeutralCurrent
 */
class ReadElectricalMeasurementNeutralCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementNeutralCurrent()
        : ReadAttribute("neutral-current")
    {
    }

    ~ReadElectricalMeasurementNeutralCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000303) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeNeutralCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.NeutralCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement NeutralCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementNeutralCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementNeutralCurrent()
        : SubscribeAttribute("neutral-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementNeutralCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000303) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNeutralCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.NeutralCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalActivePower
 */
class ReadElectricalMeasurementTotalActivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementTotalActivePower()
        : ReadAttribute("total-active-power")
    {
    }

    ~ReadElectricalMeasurementTotalActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000304) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeTotalActivePowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.TotalActivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement TotalActivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementTotalActivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementTotalActivePower()
        : SubscribeAttribute("total-active-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementTotalActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000304) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTotalActivePowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.TotalActivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalReactivePower
 */
class ReadElectricalMeasurementTotalReactivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementTotalReactivePower()
        : ReadAttribute("total-reactive-power")
    {
    }

    ~ReadElectricalMeasurementTotalReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000305) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeTotalReactivePowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.TotalReactivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement TotalReactivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementTotalReactivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementTotalReactivePower()
        : SubscribeAttribute("total-reactive-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementTotalReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000305) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTotalReactivePowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.TotalReactivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TotalApparentPower
 */
class ReadElectricalMeasurementTotalApparentPower : public ReadAttribute {
public:
    ReadElectricalMeasurementTotalApparentPower()
        : ReadAttribute("total-apparent-power")
    {
    }

    ~ReadElectricalMeasurementTotalApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000306) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeTotalApparentPowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.TotalApparentPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement TotalApparentPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementTotalApparentPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementTotalApparentPower()
        : SubscribeAttribute("total-apparent-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementTotalApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000306) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTotalApparentPowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.TotalApparentPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured1stHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured1stHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured1stHarmonicCurrent()
        : ReadAttribute("measured1st-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000307) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasured1stHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.Measured1stHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement Measured1stHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent()
        : SubscribeAttribute("measured1st-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000307) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasured1stHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured1stHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured3rdHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured3rdHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured3rdHarmonicCurrent()
        : ReadAttribute("measured3rd-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000308) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasured3rdHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.Measured3rdHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement Measured3rdHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent()
        : SubscribeAttribute("measured3rd-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000308) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasured3rdHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured3rdHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured5thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured5thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured5thHarmonicCurrent()
        : ReadAttribute("measured5th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000309) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasured5thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.Measured5thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement Measured5thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent()
        : SubscribeAttribute("measured5th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000309) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasured5thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured5thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured7thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured7thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured7thHarmonicCurrent()
        : ReadAttribute("measured7th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasured7thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.Measured7thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement Measured7thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent()
        : SubscribeAttribute("measured7th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasured7thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured7thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured9thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured9thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured9thHarmonicCurrent()
        : ReadAttribute("measured9th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasured9thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.Measured9thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement Measured9thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent()
        : SubscribeAttribute("measured9th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasured9thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured9thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Measured11thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasured11thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasured11thHarmonicCurrent()
        : ReadAttribute("measured11th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasured11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeMeasured11thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.Measured11thHarmonicCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement Measured11thHarmonicCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent()
        : SubscribeAttribute("measured11th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasured11thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.Measured11thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase1stHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent()
        : ReadAttribute("measured-phase1st-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasuredPhase1stHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase1stHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement MeasuredPhase1stHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent()
        : SubscribeAttribute("measured-phase1st-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredPhase1stHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase1stHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase3rdHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent()
        : ReadAttribute("measured-phase3rd-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasuredPhase3rdHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase3rdHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement MeasuredPhase3rdHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent()
        : SubscribeAttribute("measured-phase3rd-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredPhase3rdHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase3rdHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase5thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent()
        : ReadAttribute("measured-phase5th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000030F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasuredPhase5thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase5thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement MeasuredPhase5thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent()
        : SubscribeAttribute("measured-phase5th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000030F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredPhase5thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase5thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase7thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent()
        : ReadAttribute("measured-phase7th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000310) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasuredPhase7thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase7thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement MeasuredPhase7thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent()
        : SubscribeAttribute("measured-phase7th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000310) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredPhase7thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase7thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase9thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent()
        : ReadAttribute("measured-phase9th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000311) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasuredPhase9thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase9thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement MeasuredPhase9thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent()
        : SubscribeAttribute("measured-phase9th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000311) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredPhase9thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase9thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute MeasuredPhase11thHarmonicCurrent
 */
class ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent()
        : ReadAttribute("measured-phase11th-harmonic-current")
    {
    }

    ~ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000312) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeMeasuredPhase11thHarmonicCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase11thHarmonicCurrent response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement MeasuredPhase11thHarmonicCurrent read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent()
        : SubscribeAttribute("measured-phase11th-harmonic-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000312) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeMeasuredPhase11thHarmonicCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.MeasuredPhase11thHarmonicCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyMultiplier
 */
class ReadElectricalMeasurementAcFrequencyMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyMultiplier()
        : ReadAttribute("ac-frequency-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000400) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier()
        : SubscribeAttribute("ac-frequency-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000400) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcFrequencyMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcFrequencyDivisor
 */
class ReadElectricalMeasurementAcFrequencyDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcFrequencyDivisor()
        : ReadAttribute("ac-frequency-divisor")
    {
    }

    ~ReadElectricalMeasurementAcFrequencyDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000401) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcFrequencyDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcFrequencyDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcFrequencyDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcFrequencyDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcFrequencyDivisor()
        : SubscribeAttribute("ac-frequency-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcFrequencyDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000401) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcFrequencyDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcFrequencyDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerMultiplier
 */
class ReadElectricalMeasurementPowerMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerMultiplier()
        : ReadAttribute("power-multiplier")
    {
    }

    ~ReadElectricalMeasurementPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000402) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerMultiplier()
        : SubscribeAttribute("power-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000402) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePowerMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerDivisor
 */
class ReadElectricalMeasurementPowerDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerDivisor()
        : ReadAttribute("power-divisor")
    {
    }

    ~ReadElectricalMeasurementPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000403) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerDivisor()
        : SubscribeAttribute("power-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000403) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePowerDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute HarmonicCurrentMultiplier
 */
class ReadElectricalMeasurementHarmonicCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementHarmonicCurrentMultiplier()
        : ReadAttribute("harmonic-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000404) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeHarmonicCurrentMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.HarmonicCurrentMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement HarmonicCurrentMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier()
        : SubscribeAttribute("harmonic-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000404) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeHarmonicCurrentMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.HarmonicCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PhaseHarmonicCurrentMultiplier
 */
class ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier()
        : ReadAttribute("phase-harmonic-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000405) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributePhaseHarmonicCurrentMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PhaseHarmonicCurrentMultiplier response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement PhaseHarmonicCurrentMultiplier read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier()
        : SubscribeAttribute("phase-harmonic-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000405) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePhaseHarmonicCurrentMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PhaseHarmonicCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousVoltage
 */
class ReadElectricalMeasurementInstantaneousVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousVoltage()
        : ReadAttribute("instantaneous-voltage")
    {
    }

    ~ReadElectricalMeasurementInstantaneousVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000500) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousVoltage()
        : SubscribeAttribute("instantaneous-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000500) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstantaneousVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousLineCurrent
 */
class ReadElectricalMeasurementInstantaneousLineCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousLineCurrent()
        : ReadAttribute("instantaneous-line-current")
    {
    }

    ~ReadElectricalMeasurementInstantaneousLineCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000501) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousLineCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousLineCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousLineCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent()
        : SubscribeAttribute("instantaneous-line-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000501) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstantaneousLineCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousLineCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousActiveCurrent
 */
class ReadElectricalMeasurementInstantaneousActiveCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousActiveCurrent()
        : ReadAttribute("instantaneous-active-current")
    {
    }

    ~ReadElectricalMeasurementInstantaneousActiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000502) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousActiveCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousActiveCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousActiveCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent()
        : SubscribeAttribute("instantaneous-active-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000502) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstantaneousActiveCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousActiveCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousReactiveCurrent
 */
class ReadElectricalMeasurementInstantaneousReactiveCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousReactiveCurrent()
        : ReadAttribute("instantaneous-reactive-current")
    {
    }

    ~ReadElectricalMeasurementInstantaneousReactiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000503) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousReactiveCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousReactiveCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousReactiveCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent()
        : SubscribeAttribute("instantaneous-reactive-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000503) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstantaneousReactiveCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousReactiveCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute InstantaneousPower
 */
class ReadElectricalMeasurementInstantaneousPower : public ReadAttribute {
public:
    ReadElectricalMeasurementInstantaneousPower()
        : ReadAttribute("instantaneous-power")
    {
    }

    ~ReadElectricalMeasurementInstantaneousPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000504) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeInstantaneousPowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.InstantaneousPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement InstantaneousPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementInstantaneousPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementInstantaneousPower()
        : SubscribeAttribute("instantaneous-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementInstantaneousPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000504) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInstantaneousPowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.InstantaneousPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltage
 */
class ReadElectricalMeasurementRmsVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltage()
        : ReadAttribute("rms-voltage")
    {
    }

    ~ReadElectricalMeasurementRmsVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000505) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltage()
        : SubscribeAttribute("rms-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000505) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMin
 */
class ReadElectricalMeasurementRmsVoltageMin : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMin()
        : ReadAttribute("rms-voltage-min")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000506) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMin()
        : SubscribeAttribute("rms-voltage-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000506) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMax
 */
class ReadElectricalMeasurementRmsVoltageMax : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMax()
        : ReadAttribute("rms-voltage-max")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000507) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMax()
        : SubscribeAttribute("rms-voltage-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000507) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrent
 */
class ReadElectricalMeasurementRmsCurrent : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrent()
        : ReadAttribute("rms-current")
    {
    }

    ~ReadElectricalMeasurementRmsCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000508) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrent response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrent read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrent : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrent()
        : SubscribeAttribute("rms-current")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrent() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000508) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrent response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMin
 */
class ReadElectricalMeasurementRmsCurrentMin : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMin()
        : ReadAttribute("rms-current-min")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000509) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMin()
        : SubscribeAttribute("rms-current-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000509) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMax
 */
class ReadElectricalMeasurementRmsCurrentMax : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMax()
        : ReadAttribute("rms-current-max")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMax()
        : SubscribeAttribute("rms-current-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePower
 */
class ReadElectricalMeasurementActivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePower()
        : ReadAttribute("active-power")
    {
    }

    ~ReadElectricalMeasurementActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePower()
        : SubscribeAttribute("active-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMin
 */
class ReadElectricalMeasurementActivePowerMin : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMin()
        : ReadAttribute("active-power-min")
    {
    }

    ~ReadElectricalMeasurementActivePowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMinWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMin response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMin read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMin : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMin()
        : SubscribeAttribute("active-power-min")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMin() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerMinWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMin response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMax
 */
class ReadElectricalMeasurementActivePowerMax : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMax()
        : ReadAttribute("active-power-max")
    {
    }

    ~ReadElectricalMeasurementActivePowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMaxWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMax response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMax read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMax : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMax()
        : SubscribeAttribute("active-power-max")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMax() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerMaxWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMax response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactivePower
 */
class ReadElectricalMeasurementReactivePower : public ReadAttribute {
public:
    ReadElectricalMeasurementReactivePower()
        : ReadAttribute("reactive-power")
    {
    }

    ~ReadElectricalMeasurementReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactivePowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactivePower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactivePower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactivePower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactivePower()
        : SubscribeAttribute("reactive-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactivePower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReactivePowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactivePower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApparentPower
 */
class ReadElectricalMeasurementApparentPower : public ReadAttribute {
public:
    ReadElectricalMeasurementApparentPower()
        : ReadAttribute("apparent-power")
    {
    }

    ~ReadElectricalMeasurementApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000050F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeApparentPowerWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ApparentPower response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ApparentPower read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementApparentPower : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementApparentPower()
        : SubscribeAttribute("apparent-power")
    {
    }

    ~SubscribeAttributeElectricalMeasurementApparentPower() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000050F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApparentPowerWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ApparentPower response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerFactor
 */
class ReadElectricalMeasurementPowerFactor : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerFactor()
        : ReadAttribute("power-factor")
    {
    }

    ~ReadElectricalMeasurementPowerFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000510) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerFactorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerFactor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerFactor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerFactor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerFactor()
        : SubscribeAttribute("power-factor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerFactor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000510) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePowerFactorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerFactor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsVoltageMeasurementPeriod
 */
class ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod()
        : ReadAttribute("average-rms-voltage-measurement-period")
    {
    }

    ~ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000511) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeAverageRmsVoltageMeasurementPeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriod response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement AverageRmsVoltageMeasurementPeriod read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod()
        : WriteAttribute("average-rms-voltage-measurement-period")
    {
        AddArgument("attr-name", "average-rms-voltage-measurement-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000511) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeAverageRmsVoltageMeasurementPeriodWithValue:value
                                                                    params:params
                                                                completion:^(NSError * _Nullable error) {
                                                                    if (error != nil) {
                                                                        LogNSError("ElectricalMeasurement "
                                                                                   "AverageRmsVoltageMeasurementPeriod write Error",
                                                                            error);
                                                                    }
                                                                    SetCommandExitStatus(error);
                                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod()
        : SubscribeAttribute("average-rms-voltage-measurement-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000511) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsVoltageMeasurementPeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltageCounter
 */
class ReadElectricalMeasurementAverageRmsUnderVoltageCounter : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltageCounter()
        : ReadAttribute("average-rms-under-voltage-counter")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltageCounter() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000513) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageCounterWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounter response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounter read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementAverageRmsUnderVoltageCounter : public WriteAttribute {
public:
    WriteElectricalMeasurementAverageRmsUnderVoltageCounter()
        : WriteAttribute("average-rms-under-voltage-counter")
    {
        AddArgument("attr-name", "average-rms-under-voltage-counter");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementAverageRmsUnderVoltageCounter() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000513) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeAverageRmsUnderVoltageCounterWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "ElectricalMeasurement AverageRmsUnderVoltageCounter write Error",
                                                                  error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter()
        : SubscribeAttribute("average-rms-under-voltage-counter")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000513) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsUnderVoltageCounterWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounter response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltagePeriod
 */
class ReadElectricalMeasurementRmsExtremeOverVoltagePeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltagePeriod()
        : ReadAttribute("rms-extreme-over-voltage-period")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000514) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeOverVoltagePeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeOverVoltagePeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsExtremeOverVoltagePeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsExtremeOverVoltagePeriod()
        : WriteAttribute("rms-extreme-over-voltage-period")
    {
        AddArgument("attr-name", "rms-extreme-over-voltage-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsExtremeOverVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000514) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeRmsExtremeOverVoltagePeriodWithValue:value
                                                        params:params
                                                    completion:^(NSError * _Nullable error) {
                                                        if (error != nil) {
                                                            LogNSError(
                                                                "ElectricalMeasurement RmsExtremeOverVoltagePeriod write Error",
                                                                error);
                                                        }
                                                        SetCommandExitStatus(error);
                                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod()
        : SubscribeAttribute("rms-extreme-over-voltage-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000514) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeOverVoltagePeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltagePeriod
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod()
        : ReadAttribute("rms-extreme-under-voltage-period")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000515) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeUnderVoltagePeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeUnderVoltagePeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod()
        : WriteAttribute("rms-extreme-under-voltage-period")
    {
        AddArgument("attr-name", "rms-extreme-under-voltage-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000515) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeRmsExtremeUnderVoltagePeriodWithValue:value
                                                         params:params
                                                     completion:^(NSError * _Nullable error) {
                                                         if (error != nil) {
                                                             LogNSError(
                                                                 "ElectricalMeasurement RmsExtremeUnderVoltagePeriod write Error",
                                                                 error);
                                                         }
                                                         SetCommandExitStatus(error);
                                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod()
        : SubscribeAttribute("rms-extreme-under-voltage-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000515) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeUnderVoltagePeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSagPeriod
 */
class ReadElectricalMeasurementRmsVoltageSagPeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSagPeriod()
        : ReadAttribute("rms-voltage-sag-period")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSagPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000516) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSagPeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSagPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsVoltageSagPeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsVoltageSagPeriod()
        : WriteAttribute("rms-voltage-sag-period")
    {
        AddArgument("attr-name", "rms-voltage-sag-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsVoltageSagPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000516) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeRmsVoltageSagPeriodWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("ElectricalMeasurement RmsVoltageSagPeriod write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod()
        : SubscribeAttribute("rms-voltage-sag-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000516) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSagPeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwellPeriod
 */
class ReadElectricalMeasurementRmsVoltageSwellPeriod : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwellPeriod()
        : ReadAttribute("rms-voltage-swell-period")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwellPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000517) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSwellPeriodWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriod response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSwellPeriod read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementRmsVoltageSwellPeriod : public WriteAttribute {
public:
    WriteElectricalMeasurementRmsVoltageSwellPeriod()
        : WriteAttribute("rms-voltage-swell-period")
    {
        AddArgument("attr-name", "rms-voltage-swell-period");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementRmsVoltageSwellPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000517) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeRmsVoltageSwellPeriodWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("ElectricalMeasurement RmsVoltageSwellPeriod write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod()
        : SubscribeAttribute("rms-voltage-swell-period")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000517) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSwellPeriodWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriod response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcVoltageMultiplier
 */
class ReadElectricalMeasurementAcVoltageMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcVoltageMultiplier()
        : ReadAttribute("ac-voltage-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000600) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcVoltageMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcVoltageMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcVoltageMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcVoltageMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcVoltageMultiplier()
        : SubscribeAttribute("ac-voltage-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcVoltageMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000600) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcVoltageMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcVoltageMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcVoltageDivisor
 */
class ReadElectricalMeasurementAcVoltageDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcVoltageDivisor()
        : ReadAttribute("ac-voltage-divisor")
    {
    }

    ~ReadElectricalMeasurementAcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000601) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcVoltageDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcVoltageDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcVoltageDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcVoltageDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcVoltageDivisor()
        : SubscribeAttribute("ac-voltage-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcVoltageDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000601) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcVoltageDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcVoltageDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcCurrentMultiplier
 */
class ReadElectricalMeasurementAcCurrentMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcCurrentMultiplier()
        : ReadAttribute("ac-current-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000602) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcCurrentMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcCurrentMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcCurrentMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcCurrentMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcCurrentMultiplier()
        : SubscribeAttribute("ac-current-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcCurrentMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000602) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcCurrentMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcCurrentMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcCurrentDivisor
 */
class ReadElectricalMeasurementAcCurrentDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcCurrentDivisor()
        : ReadAttribute("ac-current-divisor")
    {
    }

    ~ReadElectricalMeasurementAcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000603) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcCurrentDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcCurrentDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcCurrentDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcCurrentDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcCurrentDivisor()
        : SubscribeAttribute("ac-current-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcCurrentDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000603) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcCurrentDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcCurrentDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcPowerMultiplier
 */
class ReadElectricalMeasurementAcPowerMultiplier : public ReadAttribute {
public:
    ReadElectricalMeasurementAcPowerMultiplier()
        : ReadAttribute("ac-power-multiplier")
    {
    }

    ~ReadElectricalMeasurementAcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000604) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcPowerMultiplierWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcPowerMultiplier response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcPowerMultiplier read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcPowerMultiplier : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcPowerMultiplier()
        : SubscribeAttribute("ac-power-multiplier")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcPowerMultiplier() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000604) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcPowerMultiplierWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcPowerMultiplier response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcPowerDivisor
 */
class ReadElectricalMeasurementAcPowerDivisor : public ReadAttribute {
public:
    ReadElectricalMeasurementAcPowerDivisor()
        : ReadAttribute("ac-power-divisor")
    {
    }

    ~ReadElectricalMeasurementAcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000605) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcPowerDivisorWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcPowerDivisor response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcPowerDivisor read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcPowerDivisor : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcPowerDivisor()
        : SubscribeAttribute("ac-power-divisor")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcPowerDivisor() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000605) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcPowerDivisorWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcPowerDivisor response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OverloadAlarmsMask
 */
class ReadElectricalMeasurementOverloadAlarmsMask : public ReadAttribute {
public:
    ReadElectricalMeasurementOverloadAlarmsMask()
        : ReadAttribute("overload-alarms-mask")
    {
    }

    ~ReadElectricalMeasurementOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000700) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeOverloadAlarmsMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.OverloadAlarmsMask response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement OverloadAlarmsMask read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementOverloadAlarmsMask : public WriteAttribute {
public:
    WriteElectricalMeasurementOverloadAlarmsMask()
        : WriteAttribute("overload-alarms-mask")
    {
        AddArgument("attr-name", "overload-alarms-mask");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000700) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeOverloadAlarmsMaskWithValue:value
                                                    params:params
                                                completion:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("ElectricalMeasurement OverloadAlarmsMask write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeElectricalMeasurementOverloadAlarmsMask : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementOverloadAlarmsMask()
        : SubscribeAttribute("overload-alarms-mask")
    {
    }

    ~SubscribeAttributeElectricalMeasurementOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000700) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOverloadAlarmsMaskWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.OverloadAlarmsMask response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VoltageOverload
 */
class ReadElectricalMeasurementVoltageOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementVoltageOverload()
        : ReadAttribute("voltage-overload")
    {
    }

    ~ReadElectricalMeasurementVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000701) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeVoltageOverloadWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.VoltageOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement VoltageOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementVoltageOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementVoltageOverload()
        : SubscribeAttribute("voltage-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000701) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVoltageOverloadWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.VoltageOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CurrentOverload
 */
class ReadElectricalMeasurementCurrentOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementCurrentOverload()
        : ReadAttribute("current-overload")
    {
    }

    ~ReadElectricalMeasurementCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000702) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeCurrentOverloadWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.CurrentOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement CurrentOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementCurrentOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementCurrentOverload()
        : SubscribeAttribute("current-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000702) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCurrentOverloadWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.CurrentOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcOverloadAlarmsMask
 */
class ReadElectricalMeasurementAcOverloadAlarmsMask : public ReadAttribute {
public:
    ReadElectricalMeasurementAcOverloadAlarmsMask()
        : ReadAttribute("ac-overload-alarms-mask")
    {
    }

    ~ReadElectricalMeasurementAcOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000800) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcOverloadAlarmsMaskWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcOverloadAlarmsMask response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcOverloadAlarmsMask read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteElectricalMeasurementAcOverloadAlarmsMask : public WriteAttribute {
public:
    WriteElectricalMeasurementAcOverloadAlarmsMask()
        : WriteAttribute("ac-overload-alarms-mask")
    {
        AddArgument("attr-name", "ac-overload-alarms-mask");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteElectricalMeasurementAcOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) WriteAttribute (0x00000800) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeAcOverloadAlarmsMaskWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("ElectricalMeasurement AcOverloadAlarmsMask write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask()
        : SubscribeAttribute("ac-overload-alarms-mask")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000800) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcOverloadAlarmsMaskWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcOverloadAlarmsMask response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcVoltageOverload
 */
class ReadElectricalMeasurementAcVoltageOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcVoltageOverload()
        : ReadAttribute("ac-voltage-overload")
    {
    }

    ~ReadElectricalMeasurementAcVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000801) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcVoltageOverloadWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcVoltageOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcVoltageOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcVoltageOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcVoltageOverload()
        : SubscribeAttribute("ac-voltage-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcVoltageOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000801) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcVoltageOverloadWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcVoltageOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcCurrentOverload
 */
class ReadElectricalMeasurementAcCurrentOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcCurrentOverload()
        : ReadAttribute("ac-current-overload")
    {
    }

    ~ReadElectricalMeasurementAcCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000802) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcCurrentOverloadWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcCurrentOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcCurrentOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcCurrentOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcCurrentOverload()
        : SubscribeAttribute("ac-current-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcCurrentOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000802) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcCurrentOverloadWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcCurrentOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcActivePowerOverload
 */
class ReadElectricalMeasurementAcActivePowerOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcActivePowerOverload()
        : ReadAttribute("ac-active-power-overload")
    {
    }

    ~ReadElectricalMeasurementAcActivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000803) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcActivePowerOverloadWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcActivePowerOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcActivePowerOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcActivePowerOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcActivePowerOverload()
        : SubscribeAttribute("ac-active-power-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcActivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000803) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcActivePowerOverloadWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcActivePowerOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcReactivePowerOverload
 */
class ReadElectricalMeasurementAcReactivePowerOverload : public ReadAttribute {
public:
    ReadElectricalMeasurementAcReactivePowerOverload()
        : ReadAttribute("ac-reactive-power-overload")
    {
    }

    ~ReadElectricalMeasurementAcReactivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000804) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcReactivePowerOverloadWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcReactivePowerOverload response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcReactivePowerOverload read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcReactivePowerOverload : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcReactivePowerOverload()
        : SubscribeAttribute("ac-reactive-power-overload")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcReactivePowerOverload() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000804) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcReactivePowerOverloadWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcReactivePowerOverload response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsOverVoltage
 */
class ReadElectricalMeasurementAverageRmsOverVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsOverVoltage()
        : ReadAttribute("average-rms-over-voltage")
    {
    }

    ~ReadElectricalMeasurementAverageRmsOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000805) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsOverVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsOverVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsOverVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage()
        : SubscribeAttribute("average-rms-over-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000805) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsOverVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltage
 */
class ReadElectricalMeasurementAverageRmsUnderVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltage()
        : ReadAttribute("average-rms-under-voltage")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000806) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage()
        : SubscribeAttribute("average-rms-under-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000806) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsUnderVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltage
 */
class ReadElectricalMeasurementRmsExtremeOverVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltage()
        : ReadAttribute("rms-extreme-over-voltage")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000807) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeOverVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeOverVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage()
        : SubscribeAttribute("rms-extreme-over-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000807) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeOverVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltage
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltage : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltage()
        : ReadAttribute("rms-extreme-under-voltage")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000808) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsExtremeUnderVoltageWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltage response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsExtremeUnderVoltage read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage()
        : SubscribeAttribute("rms-extreme-under-voltage")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000808) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeUnderVoltageWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltage response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSag
 */
class ReadElectricalMeasurementRmsVoltageSag : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSag()
        : ReadAttribute("rms-voltage-sag")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSag() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000809) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSagWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSag response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSag read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSag : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSag()
        : SubscribeAttribute("rms-voltage-sag")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSag() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000809) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSagWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSag response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwell
 */
class ReadElectricalMeasurementRmsVoltageSwell : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwell()
        : ReadAttribute("rms-voltage-swell")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwell() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000080A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSwellWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSwell response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSwell read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwell : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwell()
        : SubscribeAttribute("rms-voltage-swell")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwell() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000080A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSwellWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwell response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LineCurrentPhaseB
 */
class ReadElectricalMeasurementLineCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementLineCurrentPhaseB()
        : ReadAttribute("line-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementLineCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000901) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeLineCurrentPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.LineCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement LineCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementLineCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementLineCurrentPhaseB()
        : SubscribeAttribute("line-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementLineCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000901) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLineCurrentPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.LineCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveCurrentPhaseB
 */
class ReadElectricalMeasurementActiveCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActiveCurrentPhaseB()
        : ReadAttribute("active-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementActiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000902) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActiveCurrentPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActiveCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB()
        : SubscribeAttribute("active-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000902) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveCurrentPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactiveCurrentPhaseB
 */
class ReadElectricalMeasurementReactiveCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementReactiveCurrentPhaseB()
        : ReadAttribute("reactive-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementReactiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000903) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactiveCurrentPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactiveCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB()
        : SubscribeAttribute("reactive-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000903) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReactiveCurrentPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltagePhaseB
 */
class ReadElectricalMeasurementRmsVoltagePhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltagePhaseB()
        : ReadAttribute("rms-voltage-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltagePhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000905) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltagePhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltagePhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltagePhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB()
        : SubscribeAttribute("rms-voltage-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000905) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltagePhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltagePhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMinPhaseB
 */
class ReadElectricalMeasurementRmsVoltageMinPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMinPhaseB()
        : ReadAttribute("rms-voltage-min-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000906) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMinPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMinPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB()
        : SubscribeAttribute("rms-voltage-min-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000906) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageMinPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMaxPhaseB
 */
class ReadElectricalMeasurementRmsVoltageMaxPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMaxPhaseB()
        : ReadAttribute("rms-voltage-max-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000907) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMaxPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMaxPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB()
        : SubscribeAttribute("rms-voltage-max-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000907) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageMaxPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentPhaseB
 */
class ReadElectricalMeasurementRmsCurrentPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentPhaseB()
        : ReadAttribute("rms-current-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000908) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB()
        : SubscribeAttribute("rms-current-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000908) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMinPhaseB
 */
class ReadElectricalMeasurementRmsCurrentMinPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMinPhaseB()
        : ReadAttribute("rms-current-min-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000909) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMinPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMinPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB()
        : SubscribeAttribute("rms-current-min-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000909) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentMinPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMaxPhaseB
 */
class ReadElectricalMeasurementRmsCurrentMaxPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMaxPhaseB()
        : ReadAttribute("rms-current-max-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMaxPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMaxPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB()
        : SubscribeAttribute("rms-current-max-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentMaxPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerPhaseB
 */
class ReadElectricalMeasurementActivePowerPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerPhaseB()
        : ReadAttribute("active-power-phase-b")
    {
    }

    ~ReadElectricalMeasurementActivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerPhaseB()
        : SubscribeAttribute("active-power-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMinPhaseB
 */
class ReadElectricalMeasurementActivePowerMinPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMinPhaseB()
        : ReadAttribute("active-power-min-phase-b")
    {
    }

    ~ReadElectricalMeasurementActivePowerMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMinPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMinPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB()
        : SubscribeAttribute("active-power-min-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerMinPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMaxPhaseB
 */
class ReadElectricalMeasurementActivePowerMaxPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMaxPhaseB()
        : ReadAttribute("active-power-max-phase-b")
    {
    }

    ~ReadElectricalMeasurementActivePowerMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMaxPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMaxPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB()
        : SubscribeAttribute("active-power-max-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerMaxPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactivePowerPhaseB
 */
class ReadElectricalMeasurementReactivePowerPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementReactivePowerPhaseB()
        : ReadAttribute("reactive-power-phase-b")
    {
    }

    ~ReadElectricalMeasurementReactivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactivePowerPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactivePowerPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactivePowerPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactivePowerPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactivePowerPhaseB()
        : SubscribeAttribute("reactive-power-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactivePowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReactivePowerPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactivePowerPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApparentPowerPhaseB
 */
class ReadElectricalMeasurementApparentPowerPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementApparentPowerPhaseB()
        : ReadAttribute("apparent-power-phase-b")
    {
    }

    ~ReadElectricalMeasurementApparentPowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000090F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeApparentPowerPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ApparentPowerPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ApparentPowerPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementApparentPowerPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementApparentPowerPhaseB()
        : SubscribeAttribute("apparent-power-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementApparentPowerPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000090F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApparentPowerPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ApparentPowerPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerFactorPhaseB
 */
class ReadElectricalMeasurementPowerFactorPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerFactorPhaseB()
        : ReadAttribute("power-factor-phase-b")
    {
    }

    ~ReadElectricalMeasurementPowerFactorPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000910) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerFactorPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerFactorPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerFactorPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerFactorPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerFactorPhaseB()
        : SubscribeAttribute("power-factor-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerFactorPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000910) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePowerFactorPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerFactorPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsVoltageMeasurementPeriodPhaseB
 */
class ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB()
        : ReadAttribute("average-rms-voltage-measurement-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000911) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsVoltageMeasurementPeriodPhaseBWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsVoltageMeasurementPeriodPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB()
        : SubscribeAttribute("average-rms-voltage-measurement-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000911) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsVoltageMeasurementPeriodPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsOverVoltageCounterPhaseB
 */
class ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB()
        : ReadAttribute("average-rms-over-voltage-counter-phase-b")
    {
    }

    ~ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000912) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeAverageRmsOverVoltageCounterPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseB response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement AverageRmsOverVoltageCounterPhaseB read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB()
        : SubscribeAttribute("average-rms-over-voltage-counter-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000912) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsOverVoltageCounterPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltageCounterPhaseB
 */
class ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB()
        : ReadAttribute("average-rms-under-voltage-counter-phase-b")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000913) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageCounterPhaseBWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounterPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB()
        : SubscribeAttribute("average-rms-under-voltage-counter-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000913) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsUnderVoltageCounterPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltagePeriodPhaseB
 */
class ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB()
        : ReadAttribute("rms-extreme-over-voltage-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000914) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsExtremeOverVoltagePeriodPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseB response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsExtremeOverVoltagePeriodPhaseB read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB()
        : SubscribeAttribute("rms-extreme-over-voltage-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000914) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeOverVoltagePeriodPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltagePeriodPhaseB
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB()
        : ReadAttribute("rms-extreme-under-voltage-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000915) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsExtremeUnderVoltagePeriodPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseB response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsExtremeUnderVoltagePeriodPhaseB read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB()
        : SubscribeAttribute("rms-extreme-under-voltage-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000915) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeUnderVoltagePeriodPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSagPeriodPhaseB
 */
class ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB()
        : ReadAttribute("rms-voltage-sag-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000916) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSagPeriodPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSagPeriodPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB()
        : SubscribeAttribute("rms-voltage-sag-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000916) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSagPeriodPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwellPeriodPhaseB
 */
class ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB()
        : ReadAttribute("rms-voltage-swell-period-phase-b")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000917) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSwellPeriodPhaseBWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseB response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSwellPeriodPhaseB read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB()
        : SubscribeAttribute("rms-voltage-swell-period-phase-b")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000917) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSwellPeriodPhaseBWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseB response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LineCurrentPhaseC
 */
class ReadElectricalMeasurementLineCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementLineCurrentPhaseC()
        : ReadAttribute("line-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementLineCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A01) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeLineCurrentPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.LineCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement LineCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementLineCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementLineCurrentPhaseC()
        : SubscribeAttribute("line-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementLineCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A01) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLineCurrentPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.LineCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActiveCurrentPhaseC
 */
class ReadElectricalMeasurementActiveCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActiveCurrentPhaseC()
        : ReadAttribute("active-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementActiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A02) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActiveCurrentPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActiveCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC()
        : SubscribeAttribute("active-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A02) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActiveCurrentPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActiveCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactiveCurrentPhaseC
 */
class ReadElectricalMeasurementReactiveCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementReactiveCurrentPhaseC()
        : ReadAttribute("reactive-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementReactiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A03) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactiveCurrentPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactiveCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC()
        : SubscribeAttribute("reactive-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A03) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReactiveCurrentPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactiveCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltagePhaseC
 */
class ReadElectricalMeasurementRmsVoltagePhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltagePhaseC()
        : ReadAttribute("rms-voltage-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltagePhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A05) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltagePhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltagePhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltagePhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC()
        : SubscribeAttribute("rms-voltage-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A05) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltagePhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltagePhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMinPhaseC
 */
class ReadElectricalMeasurementRmsVoltageMinPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMinPhaseC()
        : ReadAttribute("rms-voltage-min-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A06) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMinPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMinPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC()
        : SubscribeAttribute("rms-voltage-min-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A06) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageMinPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMinPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageMaxPhaseC
 */
class ReadElectricalMeasurementRmsVoltageMaxPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageMaxPhaseC()
        : ReadAttribute("rms-voltage-max-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A07) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageMaxPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageMaxPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC()
        : SubscribeAttribute("rms-voltage-max-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A07) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageMaxPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageMaxPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentPhaseC
 */
class ReadElectricalMeasurementRmsCurrentPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentPhaseC()
        : ReadAttribute("rms-current-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A08) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC()
        : SubscribeAttribute("rms-current-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A08) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMinPhaseC
 */
class ReadElectricalMeasurementRmsCurrentMinPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMinPhaseC()
        : ReadAttribute("rms-current-min-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A09) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMinPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMinPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC()
        : SubscribeAttribute("rms-current-min-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A09) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentMinPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMinPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsCurrentMaxPhaseC
 */
class ReadElectricalMeasurementRmsCurrentMaxPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsCurrentMaxPhaseC()
        : ReadAttribute("rms-current-max-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsCurrentMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsCurrentMaxPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsCurrentMaxPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC()
        : SubscribeAttribute("rms-current-max-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsCurrentMaxPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsCurrentMaxPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerPhaseC
 */
class ReadElectricalMeasurementActivePowerPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerPhaseC()
        : ReadAttribute("active-power-phase-c")
    {
    }

    ~ReadElectricalMeasurementActivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerPhaseC()
        : SubscribeAttribute("active-power-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMinPhaseC
 */
class ReadElectricalMeasurementActivePowerMinPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMinPhaseC()
        : ReadAttribute("active-power-min-phase-c")
    {
    }

    ~ReadElectricalMeasurementActivePowerMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMinPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMinPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC()
        : SubscribeAttribute("active-power-min-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerMinPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMinPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ActivePowerMaxPhaseC
 */
class ReadElectricalMeasurementActivePowerMaxPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementActivePowerMaxPhaseC()
        : ReadAttribute("active-power-max-phase-c")
    {
    }

    ~ReadElectricalMeasurementActivePowerMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeActivePowerMaxPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ActivePowerMaxPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC()
        : SubscribeAttribute("active-power-max-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeActivePowerMaxPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ActivePowerMaxPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ReactivePowerPhaseC
 */
class ReadElectricalMeasurementReactivePowerPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementReactivePowerPhaseC()
        : ReadAttribute("reactive-power-phase-c")
    {
    }

    ~ReadElectricalMeasurementReactivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeReactivePowerPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ReactivePowerPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ReactivePowerPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementReactivePowerPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementReactivePowerPhaseC()
        : SubscribeAttribute("reactive-power-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementReactivePowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeReactivePowerPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ReactivePowerPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ApparentPowerPhaseC
 */
class ReadElectricalMeasurementApparentPowerPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementApparentPowerPhaseC()
        : ReadAttribute("apparent-power-phase-c")
    {
    }

    ~ReadElectricalMeasurementApparentPowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A0F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeApparentPowerPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ApparentPowerPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ApparentPowerPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementApparentPowerPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementApparentPowerPhaseC()
        : SubscribeAttribute("apparent-power-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementApparentPowerPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A0F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeApparentPowerPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ApparentPowerPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute PowerFactorPhaseC
 */
class ReadElectricalMeasurementPowerFactorPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementPowerFactorPhaseC()
        : ReadAttribute("power-factor-phase-c")
    {
    }

    ~ReadElectricalMeasurementPowerFactorPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A10) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributePowerFactorPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.PowerFactorPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement PowerFactorPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementPowerFactorPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementPowerFactorPhaseC()
        : SubscribeAttribute("power-factor-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementPowerFactorPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A10) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributePowerFactorPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.PowerFactorPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsVoltageMeasurementPeriodPhaseC
 */
class ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC()
        : ReadAttribute("average-rms-voltage-measurement-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A11) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsVoltageMeasurementPeriodPhaseCWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsVoltageMeasurementPeriodPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC()
        : SubscribeAttribute("average-rms-voltage-measurement-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A11) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsVoltageMeasurementPeriodPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsVoltageMeasurementPeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsOverVoltageCounterPhaseC
 */
class ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC()
        : ReadAttribute("average-rms-over-voltage-counter-phase-c")
    {
    }

    ~ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A12) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeAverageRmsOverVoltageCounterPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseC response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement AverageRmsOverVoltageCounterPhaseC read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC()
        : SubscribeAttribute("average-rms-over-voltage-counter-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A12) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsOverVoltageCounterPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsOverVoltageCounterPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AverageRmsUnderVoltageCounterPhaseC
 */
class ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC()
        : ReadAttribute("average-rms-under-voltage-counter-phase-c")
    {
    }

    ~ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A13) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAverageRmsUnderVoltageCounterPhaseCWithCompletion:^(
            NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AverageRmsUnderVoltageCounterPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC()
        : SubscribeAttribute("average-rms-under-voltage-counter-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A13) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAverageRmsUnderVoltageCounterPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AverageRmsUnderVoltageCounterPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeOverVoltagePeriodPhaseC
 */
class ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC()
        : ReadAttribute("rms-extreme-over-voltage-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A14) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsExtremeOverVoltagePeriodPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseC response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsExtremeOverVoltagePeriodPhaseC read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC()
        : SubscribeAttribute("rms-extreme-over-voltage-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A14) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeOverVoltagePeriodPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeOverVoltagePeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsExtremeUnderVoltagePeriodPhaseC
 */
class ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC()
        : ReadAttribute("rms-extreme-under-voltage-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A15) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster
            readAttributeRmsExtremeUnderVoltagePeriodPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseC response %@", [value description]);
                if (error != nil) {
                    LogNSError("ElectricalMeasurement RmsExtremeUnderVoltagePeriodPhaseC read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC()
        : SubscribeAttribute("rms-extreme-under-voltage-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A15) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsExtremeUnderVoltagePeriodPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsExtremeUnderVoltagePeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSagPeriodPhaseC
 */
class ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC()
        : ReadAttribute("rms-voltage-sag-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A16) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSagPeriodPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSagPeriodPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC()
        : SubscribeAttribute("rms-voltage-sag-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A16) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSagPeriodPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSagPeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RmsVoltageSwellPeriodPhaseC
 */
class ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC : public ReadAttribute {
public:
    ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC()
        : ReadAttribute("rms-voltage-swell-period-phase-c")
    {
    }

    ~ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x00000A17) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeRmsVoltageSwellPeriodPhaseCWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseC response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement RmsVoltageSwellPeriodPhaseC read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC()
        : SubscribeAttribute("rms-voltage-swell-period-phase-c")
    {
    }

    ~SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x00000A17) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRmsVoltageSwellPeriodPhaseCWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.RmsVoltageSwellPeriodPhaseC response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadElectricalMeasurementGeneratedCommandList : public ReadAttribute {
public:
    ReadElectricalMeasurementGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadElectricalMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadElectricalMeasurementAcceptedCommandList : public ReadAttribute {
public:
    ReadElectricalMeasurementAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadElectricalMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadElectricalMeasurementAttributeList : public ReadAttribute {
public:
    ReadElectricalMeasurementAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadElectricalMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeElectricalMeasurementAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadElectricalMeasurementFeatureMap : public ReadAttribute {
public:
    ReadElectricalMeasurementFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadElectricalMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeElectricalMeasurementFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadElectricalMeasurementClusterRevision : public ReadAttribute {
public:
    ReadElectricalMeasurementClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadElectricalMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"ElectricalMeasurement.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("ElectricalMeasurement ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeElectricalMeasurementClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeElectricalMeasurementClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeElectricalMeasurementClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0x00000B04) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterElectricalMeasurement * cluster = [[MTRBaseClusterElectricalMeasurement alloc] initWithDevice:device
                                                                                                         endpointID:@(endpointId)
                                                                                                              queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"ElectricalMeasurement.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Cluster TestCluster                                                 | 0xFFF1FC05|
|------------------------------------------------------------------------------|
| Commands:                                                           |        |
| * Test                                                              |   0x00 |
| * TestNotHandled                                                    |   0x01 |
| * TestSpecific                                                      |   0x02 |
| * TestUnknownCommand                                                |   0x03 |
| * TestAddArguments                                                  |   0x04 |
| * TestSimpleArgumentRequest                                         |   0x05 |
| * TestStructArrayArgumentRequest                                    |   0x06 |
| * TestStructArgumentRequest                                         |   0x07 |
| * TestNestedStructArgumentRequest                                   |   0x08 |
| * TestListStructArgumentRequest                                     |   0x09 |
| * TestListInt8UArgumentRequest                                      |   0x0A |
| * TestNestedStructListArgumentRequest                               |   0x0B |
| * TestListNestedStructListArgumentRequest                           |   0x0C |
| * TestListInt8UReverseRequest                                       |   0x0D |
| * TestEnumsRequest                                                  |   0x0E |
| * TestNullableOptionalRequest                                       |   0x0F |
| * TestComplexNullableOptionalRequest                                |   0x10 |
| * SimpleStructEchoRequest                                           |   0x11 |
| * TimedInvokeRequest                                                |   0x12 |
| * TestSimpleOptionalArgumentRequest                                 |   0x13 |
| * TestEmitTestEventRequest                                          |   0x14 |
| * TestEmitTestFabricScopedEventRequest                              |   0x15 |
|------------------------------------------------------------------------------|
| Attributes:                                                         |        |
| * Boolean                                                           | 0x0000 |
| * Bitmap8                                                           | 0x0001 |
| * Bitmap16                                                          | 0x0002 |
| * Bitmap32                                                          | 0x0003 |
| * Bitmap64                                                          | 0x0004 |
| * Int8u                                                             | 0x0005 |
| * Int16u                                                            | 0x0006 |
| * Int24u                                                            | 0x0007 |
| * Int32u                                                            | 0x0008 |
| * Int40u                                                            | 0x0009 |
| * Int48u                                                            | 0x000A |
| * Int56u                                                            | 0x000B |
| * Int64u                                                            | 0x000C |
| * Int8s                                                             | 0x000D |
| * Int16s                                                            | 0x000E |
| * Int24s                                                            | 0x000F |
| * Int32s                                                            | 0x0010 |
| * Int40s                                                            | 0x0011 |
| * Int48s                                                            | 0x0012 |
| * Int56s                                                            | 0x0013 |
| * Int64s                                                            | 0x0014 |
| * Enum8                                                             | 0x0015 |
| * Enum16                                                            | 0x0016 |
| * FloatSingle                                                       | 0x0017 |
| * FloatDouble                                                       | 0x0018 |
| * OctetString                                                       | 0x0019 |
| * ListInt8u                                                         | 0x001A |
| * ListOctetString                                                   | 0x001B |
| * ListStructOctetString                                             | 0x001C |
| * LongOctetString                                                   | 0x001D |
| * CharString                                                        | 0x001E |
| * LongCharString                                                    | 0x001F |
| * EpochUs                                                           | 0x0020 |
| * EpochS                                                            | 0x0021 |
| * VendorId                                                          | 0x0022 |
| * ListNullablesAndOptionalsStruct                                   | 0x0023 |
| * EnumAttr                                                          | 0x0024 |
| * StructAttr                                                        | 0x0025 |
| * RangeRestrictedInt8u                                              | 0x0026 |
| * RangeRestrictedInt8s                                              | 0x0027 |
| * RangeRestrictedInt16u                                             | 0x0028 |
| * RangeRestrictedInt16s                                             | 0x0029 |
| * ListLongOctetString                                               | 0x002A |
| * ListFabricScoped                                                  | 0x002B |
| * TimedWriteBoolean                                                 | 0x0030 |
| * GeneralErrorBoolean                                               | 0x0031 |
| * ClusterErrorBoolean                                               | 0x0032 |
| * Unsupported                                                       | 0x00FF |
| * NullableBoolean                                                   | 0x4000 |
| * NullableBitmap8                                                   | 0x4001 |
| * NullableBitmap16                                                  | 0x4002 |
| * NullableBitmap32                                                  | 0x4003 |
| * NullableBitmap64                                                  | 0x4004 |
| * NullableInt8u                                                     | 0x4005 |
| * NullableInt16u                                                    | 0x4006 |
| * NullableInt24u                                                    | 0x4007 |
| * NullableInt32u                                                    | 0x4008 |
| * NullableInt40u                                                    | 0x4009 |
| * NullableInt48u                                                    | 0x400A |
| * NullableInt56u                                                    | 0x400B |
| * NullableInt64u                                                    | 0x400C |
| * NullableInt8s                                                     | 0x400D |
| * NullableInt16s                                                    | 0x400E |
| * NullableInt24s                                                    | 0x400F |
| * NullableInt32s                                                    | 0x4010 |
| * NullableInt40s                                                    | 0x4011 |
| * NullableInt48s                                                    | 0x4012 |
| * NullableInt56s                                                    | 0x4013 |
| * NullableInt64s                                                    | 0x4014 |
| * NullableEnum8                                                     | 0x4015 |
| * NullableEnum16                                                    | 0x4016 |
| * NullableFloatSingle                                               | 0x4017 |
| * NullableFloatDouble                                               | 0x4018 |
| * NullableOctetString                                               | 0x4019 |
| * NullableCharString                                                | 0x401E |
| * NullableEnumAttr                                                  | 0x4024 |
| * NullableStruct                                                    | 0x4025 |
| * NullableRangeRestrictedInt8u                                      | 0x4026 |
| * NullableRangeRestrictedInt8s                                      | 0x4027 |
| * NullableRangeRestrictedInt16u                                     | 0x4028 |
| * NullableRangeRestrictedInt16s                                     | 0x4029 |
| * WriteOnlyInt8u                                                    | 0x402A |
| * GeneratedCommandList                                              | 0xFFF8 |
| * AcceptedCommandList                                               | 0xFFF9 |
| * AttributeList                                                     | 0xFFFB |
| * FeatureMap                                                        | 0xFFFC |
| * ClusterRevision                                                   | 0xFFFD |
|------------------------------------------------------------------------------|
| Events:                                                             |        |
| * TestEvent                                                         | 0x0001 |
| * TestFabricScopedEvent                                             | 0x0002 |
\*----------------------------------------------------------------------------*/

/*
 * Command Test
 */
class TestClusterTest : public ClusterCommand {
public:
    TestClusterTest()
        : ClusterCommand("test")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testWithParams:params
                         completion:^(NSError * _Nullable error) {
                             responsesNeeded--;
                             if (error != nil) {
                                 mError = error;
                                 LogNSError("Error", error);
                             }
                             if (responsesNeeded == 0) {
                                 SetCommandExitStatus(mError);
                             }
                         }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestNotHandled
 */
class TestClusterTestNotHandled : public ClusterCommand {
public:
    TestClusterTestNotHandled()
        : ClusterCommand("test-not-handled")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNotHandledParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testNotHandledWithParams:params
                                   completion:^(NSError * _Nullable error) {
                                       responsesNeeded--;
                                       if (error != nil) {
                                           mError = error;
                                           LogNSError("Error", error);
                                       }
                                       if (responsesNeeded == 0) {
                                           SetCommandExitStatus(mError);
                                       }
                                   }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestSpecific
 */
class TestClusterTestSpecific : public ClusterCommand {
public:
    TestClusterTestSpecific()
        : ClusterCommand("test-specific")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestSpecificParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testSpecificWithParams:params
                                 completion:^(MTRTestClusterClusterTestSpecificResponseParams * _Nullable values,
                                     NSError * _Nullable error) {
                                     NSLog(@"Values: %@", values);
                                     responsesNeeded--;
                                     if (error != nil) {
                                         mError = error;
                                         LogNSError("Error", error);
                                     }
                                     if (responsesNeeded == 0) {
                                         SetCommandExitStatus(mError);
                                     }
                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestUnknownCommand
 */
class TestClusterTestUnknownCommand : public ClusterCommand {
public:
    TestClusterTestUnknownCommand()
        : ClusterCommand("test-unknown-command")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestUnknownCommandParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testUnknownCommandWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestAddArguments
 */
class TestClusterTestAddArguments : public ClusterCommand {
public:
    TestClusterTestAddArguments()
        : ClusterCommand("test-add-arguments")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        AddArgument("Arg2", 0, UINT8_MAX, &mRequest.arg2);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestAddArgumentsParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1];
        params.arg2 = [NSNumber numberWithUnsignedChar:mRequest.arg2];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testAddArgumentsWithParams:params
                                     completion:^(MTRTestClusterClusterTestAddArgumentsResponseParams * _Nullable values,
                                         NSError * _Nullable error) {
                                         NSLog(@"Values: %@", values);
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestAddArguments::Type mRequest;
};

/*
 * Command TestSimpleArgumentRequest
 */
class TestClusterTestSimpleArgumentRequest : public ClusterCommand {
public:
    TestClusterTestSimpleArgumentRequest()
        : ClusterCommand("test-simple-argument-request")
    {
        AddArgument("Arg1", 0, 1, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestSimpleArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithBool:mRequest.arg1];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testSimpleArgumentRequestWithParams:params
                                              completion:^(MTRTestClusterClusterTestSimpleArgumentResponseParams * _Nullable values,
                                                  NSError * _Nullable error) {
                                                  NSLog(@"Values: %@", values);
                                                  responsesNeeded--;
                                                  if (error != nil) {
                                                      mError = error;
                                                      LogNSError("Error", error);
                                                  }
                                                  if (responsesNeeded == 0) {
                                                      SetCommandExitStatus(mError);
                                                  }
                                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestSimpleArgumentRequest::Type mRequest;
};

/*
 * Command TestStructArrayArgumentRequest
 */
class TestClusterTestStructArrayArgumentRequest : public ClusterCommand {
public:
    TestClusterTestStructArrayArgumentRequest()
        : ClusterCommand("test-struct-array-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
        , mComplex_Arg2(&mRequest.arg2)
        , mComplex_Arg3(&mRequest.arg3)
        , mComplex_Arg4(&mRequest.arg4)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        AddArgument("Arg2", &mComplex_Arg2);
        AddArgument("Arg3", &mComplex_Arg3);
        AddArgument("Arg4", &mComplex_Arg4);
        AddArgument("Arg5", 0, UINT8_MAX, &mRequest.arg5);
        AddArgument("Arg6", 0, 1, &mRequest.arg6);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestStructArrayArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                MTRTestClusterClusterNestedStructList * newElement_0;
                newElement_0 = [MTRTestClusterClusterNestedStructList new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.c.a = [NSNumber numberWithUnsignedChar:entry_0.c.a];
                newElement_0.c.b = [NSNumber numberWithBool:entry_0.c.b];
                newElement_0.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c.c)];
                newElement_0.c.d = [NSData dataWithBytes:entry_0.c.d.data() length:entry_0.c.d.size()];
                newElement_0.c.e = [[NSString alloc] initWithBytes:entry_0.c.e.data()
                                                            length:entry_0.c.e.size()
                                                          encoding:NSUTF8StringEncoding];
                newElement_0.c.f = [NSNumber numberWithUnsignedChar:entry_0.c.f.Raw()];
                newElement_0.c.g = [NSNumber numberWithFloat:entry_0.c.g];
                newElement_0.c.h = [NSNumber numberWithDouble:entry_0.c.h];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.d) {
                        MTRTestClusterClusterSimpleStruct * newElement_2;
                        newElement_2 = [MTRTestClusterClusterSimpleStruct new];
                        newElement_2.a = [NSNumber numberWithUnsignedChar:entry_2.a];
                        newElement_2.b = [NSNumber numberWithBool:entry_2.b];
                        newElement_2.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_2.c)];
                        newElement_2.d = [NSData dataWithBytes:entry_2.d.data() length:entry_2.d.size()];
                        newElement_2.e = [[NSString alloc] initWithBytes:entry_2.e.data()
                                                                  length:entry_2.e.size()
                                                                encoding:NSUTF8StringEncoding];
                        newElement_2.f = [NSNumber numberWithUnsignedChar:entry_2.f.Raw()];
                        newElement_2.g = [NSNumber numberWithFloat:entry_2.g];
                        newElement_2.h = [NSNumber numberWithDouble:entry_2.h];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.d = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.e) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedInt:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.e = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.f) {
                        NSData * newElement_2;
                        newElement_2 = [NSData dataWithBytes:entry_2.data() length:entry_2.size()];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.f = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.g) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.g = array_2;
                }
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg2) {
                MTRTestClusterClusterSimpleStruct * newElement_0;
                newElement_0 = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c)];
                newElement_0.d = [NSData dataWithBytes:entry_0.d.data() length:entry_0.d.size()];
                newElement_0.e = [[NSString alloc] initWithBytes:entry_0.e.data()
                                                          length:entry_0.e.size()
                                                        encoding:NSUTF8StringEncoding];
                newElement_0.f = [NSNumber numberWithUnsignedChar:entry_0.f.Raw()];
                newElement_0.g = [NSNumber numberWithFloat:entry_0.g];
                newElement_0.h = [NSNumber numberWithDouble:entry_0.h];
                [array_0 addObject:newElement_0];
            }
            params.arg2 = array_0;
        }
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg3) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0)];
                [array_0 addObject:newElement_0];
            }
            params.arg3 = array_0;
        }
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg4) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithBool:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.arg4 = array_0;
        }
        params.arg5 = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg5)];
        params.arg6 = [NSNumber numberWithBool:mRequest.arg6];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testStructArrayArgumentRequestWithParams:params
                                              completion:^(
                                                  MTRTestClusterClusterTestStructArrayArgumentResponseParams * _Nullable values,
                                                  NSError * _Nullable error) {
                                                  NSLog(@"Values: %@", values);
                                                  responsesNeeded--;
                                                  if (error != nil) {
                                                      mError = error;
                                                      LogNSError("Error", error);
                                                  }
                                                  if (responsesNeeded == 0) {
                                                      SetCommandExitStatus(mError);
                                                  }
                                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestStructArrayArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NestedStructList::Type>>
        mComplex_Arg1;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>
        mComplex_Arg2;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>> mComplex_Arg3;
    TypedComplexArgument<chip::app::DataModel::List<const bool>> mComplex_Arg4;
};

/*
 * Command TestStructArgumentRequest
 */
class TestClusterTestStructArgumentRequest : public ClusterCommand {
public:
    TestClusterTestStructArgumentRequest()
        : ClusterCommand("test-struct-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c)];
        params.arg1.d = [NSData dataWithBytes:mRequest.arg1.d.data() length:mRequest.arg1.d.size()];
        params.arg1.e = [[NSString alloc] initWithBytes:mRequest.arg1.e.data()
                                                 length:mRequest.arg1.e.size()
                                               encoding:NSUTF8StringEncoding];
        params.arg1.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.f.Raw()];
        params.arg1.g = [NSNumber numberWithFloat:mRequest.arg1.g];
        params.arg1.h = [NSNumber numberWithDouble:mRequest.arg1.h];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testStructArgumentRequestWithParams:params
                                              completion:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                  NSError * _Nullable error) {
                                                  NSLog(@"Values: %@", values);
                                                  responsesNeeded--;
                                                  if (error != nil) {
                                                      mError = error;
                                                      LogNSError("Error", error);
                                                  }
                                                  if (responsesNeeded == 0) {
                                                      SetCommandExitStatus(mError);
                                                  }
                                              }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mComplex_Arg1;
};

/*
 * Command TestNestedStructArgumentRequest
 */
class TestClusterTestNestedStructArgumentRequest : public ClusterCommand {
public:
    TestClusterTestNestedStructArgumentRequest()
        : ClusterCommand("test-nested-struct-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNestedStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterNestedStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.c.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.a];
        params.arg1.c.b = [NSNumber numberWithBool:mRequest.arg1.c.b];
        params.arg1.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c.c)];
        params.arg1.c.d = [NSData dataWithBytes:mRequest.arg1.c.d.data() length:mRequest.arg1.c.d.size()];
        params.arg1.c.e = [[NSString alloc] initWithBytes:mRequest.arg1.c.e.data()
                                                   length:mRequest.arg1.c.e.size()
                                                 encoding:NSUTF8StringEncoding];
        params.arg1.c.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.f.Raw()];
        params.arg1.c.g = [NSNumber numberWithFloat:mRequest.arg1.c.g];
        params.arg1.c.h = [NSNumber numberWithDouble:mRequest.arg1.c.h];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testNestedStructArgumentRequestWithParams:params
                                                    completion:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                        NSError * _Nullable error) {
                                                        NSLog(@"Values: %@", values);
                                                        responsesNeeded--;
                                                        if (error != nil) {
                                                            mError = error;
                                                            LogNSError("Error", error);
                                                        }
                                                        if (responsesNeeded == 0) {
                                                            SetCommandExitStatus(mError);
                                                        }
                                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestNestedStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::NestedStruct::Type> mComplex_Arg1;
};

/*
 * Command TestListStructArgumentRequest
 */
class TestClusterTestListStructArgumentRequest : public ClusterCommand {
public:
    TestClusterTestListStructArgumentRequest()
        : ClusterCommand("test-list-struct-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListStructArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                MTRTestClusterClusterSimpleStruct * newElement_0;
                newElement_0 = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c)];
                newElement_0.d = [NSData dataWithBytes:entry_0.d.data() length:entry_0.d.size()];
                newElement_0.e = [[NSString alloc] initWithBytes:entry_0.e.data()
                                                          length:entry_0.e.size()
                                                        encoding:NSUTF8StringEncoding];
                newElement_0.f = [NSNumber numberWithUnsignedChar:entry_0.f.Raw()];
                newElement_0.g = [NSNumber numberWithFloat:entry_0.g];
                newElement_0.h = [NSNumber numberWithDouble:entry_0.h];
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testListStructArgumentRequestWithParams:params
                                                  completion:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                      NSError * _Nullable error) {
                                                      NSLog(@"Values: %@", values);
                                                      responsesNeeded--;
                                                      if (error != nil) {
                                                          mError = error;
                                                          LogNSError("Error", error);
                                                      }
                                                      if (responsesNeeded == 0) {
                                                          SetCommandExitStatus(mError);
                                                      }
                                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListStructArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>
        mComplex_Arg1;
};

/*
 * Command TestListInt8UArgumentRequest
 */
class TestClusterTestListInt8UArgumentRequest : public ClusterCommand {
public:
    TestClusterTestListInt8UArgumentRequest()
        : ClusterCommand("test-list-int8uargument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListInt8UArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testListInt8UArgumentRequestWithParams:params
                                                 completion:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                     NSError * _Nullable error) {
                                                     NSLog(@"Values: %@", values);
                                                     responsesNeeded--;
                                                     if (error != nil) {
                                                         mError = error;
                                                         LogNSError("Error", error);
                                                     }
                                                     if (responsesNeeded == 0) {
                                                         SetCommandExitStatus(mError);
                                                     }
                                                 }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListInt8UArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex_Arg1;
};

/*
 * Command TestNestedStructListArgumentRequest
 */
class TestClusterTestNestedStructListArgumentRequest : public ClusterCommand {
public:
    TestClusterTestNestedStructListArgumentRequest()
        : ClusterCommand("test-nested-struct-list-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNestedStructListArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterNestedStructList new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.c.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.a];
        params.arg1.c.b = [NSNumber numberWithBool:mRequest.arg1.c.b];
        params.arg1.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c.c)];
        params.arg1.c.d = [NSData dataWithBytes:mRequest.arg1.c.d.data() length:mRequest.arg1.c.d.size()];
        params.arg1.c.e = [[NSString alloc] initWithBytes:mRequest.arg1.c.e.data()
                                                   length:mRequest.arg1.c.e.size()
                                                 encoding:NSUTF8StringEncoding];
        params.arg1.c.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.c.f.Raw()];
        params.arg1.c.g = [NSNumber numberWithFloat:mRequest.arg1.c.g];
        params.arg1.c.h = [NSNumber numberWithDouble:mRequest.arg1.c.h];
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.d) {
                MTRTestClusterClusterSimpleStruct * newElement_1;
                newElement_1 = [MTRTestClusterClusterSimpleStruct new];
                newElement_1.a = [NSNumber numberWithUnsignedChar:entry_1.a];
                newElement_1.b = [NSNumber numberWithBool:entry_1.b];
                newElement_1.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1.c)];
                newElement_1.d = [NSData dataWithBytes:entry_1.d.data() length:entry_1.d.size()];
                newElement_1.e = [[NSString alloc] initWithBytes:entry_1.e.data()
                                                          length:entry_1.e.size()
                                                        encoding:NSUTF8StringEncoding];
                newElement_1.f = [NSNumber numberWithUnsignedChar:entry_1.f.Raw()];
                newElement_1.g = [NSNumber numberWithFloat:entry_1.g];
                newElement_1.h = [NSNumber numberWithDouble:entry_1.h];
                [array_1 addObject:newElement_1];
            }
            params.arg1.d = array_1;
        }
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.e) {
                NSNumber * newElement_1;
                newElement_1 = [NSNumber numberWithUnsignedInt:entry_1];
                [array_1 addObject:newElement_1];
            }
            params.arg1.e = array_1;
        }
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.f) {
                NSData * newElement_1;
                newElement_1 = [NSData dataWithBytes:entry_1.data() length:entry_1.size()];
                [array_1 addObject:newElement_1];
            }
            params.arg1.f = array_1;
        }
        { // Scope for our temporary variables
            auto * array_1 = [NSMutableArray new];
            for (auto & entry_1 : mRequest.arg1.g) {
                NSNumber * newElement_1;
                newElement_1 = [NSNumber numberWithUnsignedChar:entry_1];
                [array_1 addObject:newElement_1];
            }
            params.arg1.g = array_1;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testNestedStructListArgumentRequestWithParams:params
                                                        completion:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                            NSError * _Nullable error) {
                                                            NSLog(@"Values: %@", values);
                                                            responsesNeeded--;
                                                            if (error != nil) {
                                                                mError = error;
                                                                LogNSError("Error", error);
                                                            }
                                                            if (responsesNeeded == 0) {
                                                                SetCommandExitStatus(mError);
                                                            }
                                                        }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestNestedStructListArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::NestedStructList::Type> mComplex_Arg1;
};

/*
 * Command TestListNestedStructListArgumentRequest
 */
class TestClusterTestListNestedStructListArgumentRequest : public ClusterCommand {
public:
    TestClusterTestListNestedStructListArgumentRequest()
        : ClusterCommand("test-list-nested-struct-list-argument-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListNestedStructListArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                MTRTestClusterClusterNestedStructList * newElement_0;
                newElement_0 = [MTRTestClusterClusterNestedStructList new];
                newElement_0.a = [NSNumber numberWithUnsignedChar:entry_0.a];
                newElement_0.b = [NSNumber numberWithBool:entry_0.b];
                newElement_0.c = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.c.a = [NSNumber numberWithUnsignedChar:entry_0.c.a];
                newElement_0.c.b = [NSNumber numberWithBool:entry_0.c.b];
                newElement_0.c.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.c.c)];
                newElement_0.c.d = [NSData dataWithBytes:entry_0.c.d.data() length:entry_0.c.d.size()];
                newElement_0.c.e = [[NSString alloc] initWithBytes:entry_0.c.e.data()
                                                            length:entry_0.c.e.size()
                                                          encoding:NSUTF8StringEncoding];
                newElement_0.c.f = [NSNumber numberWithUnsignedChar:entry_0.c.f.Raw()];
                newElement_0.c.g = [NSNumber numberWithFloat:entry_0.c.g];
                newElement_0.c.h = [NSNumber numberWithDouble:entry_0.c.h];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.d) {
                        MTRTestClusterClusterSimpleStruct * newElement_2;
                        newElement_2 = [MTRTestClusterClusterSimpleStruct new];
                        newElement_2.a = [NSNumber numberWithUnsignedChar:entry_2.a];
                        newElement_2.b = [NSNumber numberWithBool:entry_2.b];
                        newElement_2.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_2.c)];
                        newElement_2.d = [NSData dataWithBytes:entry_2.d.data() length:entry_2.d.size()];
                        newElement_2.e = [[NSString alloc] initWithBytes:entry_2.e.data()
                                                                  length:entry_2.e.size()
                                                                encoding:NSUTF8StringEncoding];
                        newElement_2.f = [NSNumber numberWithUnsignedChar:entry_2.f.Raw()];
                        newElement_2.g = [NSNumber numberWithFloat:entry_2.g];
                        newElement_2.h = [NSNumber numberWithDouble:entry_2.h];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.d = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.e) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedInt:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.e = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.f) {
                        NSData * newElement_2;
                        newElement_2 = [NSData dataWithBytes:entry_2.data() length:entry_2.size()];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.f = array_2;
                }
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.g) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.g = array_2;
                }
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testListNestedStructListArgumentRequestWithParams:params
                                                       completion:^(MTRTestClusterClusterBooleanResponseParams * _Nullable values,
                                                           NSError * _Nullable error) {
                                                           NSLog(@"Values: %@", values);
                                                           responsesNeeded--;
                                                           if (error != nil) {
                                                               mError = error;
                                                               LogNSError("Error", error);
                                                           }
                                                           if (responsesNeeded == 0) {
                                                               SetCommandExitStatus(mError);
                                                           }
                                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListNestedStructListArgumentRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NestedStructList::Type>>
        mComplex_Arg1;
};

/*
 * Command TestListInt8UReverseRequest
 */
class TestClusterTestListInt8UReverseRequest : public ClusterCommand {
public:
    TestClusterTestListInt8UReverseRequest()
        : ClusterCommand("test-list-int8ureverse-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestListInt8UReverseRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        { // Scope for our temporary variables
            auto * array_0 = [NSMutableArray new];
            for (auto & entry_0 : mRequest.arg1) {
                NSNumber * newElement_0;
                newElement_0 = [NSNumber numberWithUnsignedChar:entry_0];
                [array_0 addObject:newElement_0];
            }
            params.arg1 = array_0;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testListInt8UReverseRequestWithParams:params
                                           completion:^(MTRTestClusterClusterTestListInt8UReverseResponseParams * _Nullable values,
                                               NSError * _Nullable error) {
                                               NSLog(@"Values: %@", values);
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestListInt8UReverseRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex_Arg1;
};

/*
 * Command TestEnumsRequest
 */
class TestClusterTestEnumsRequest : public ClusterCommand {
public:
    TestClusterTestEnumsRequest()
        : ClusterCommand("test-enums-request")
    {
        AddArgument("Arg1", 0, UINT16_MAX, &mRequest.arg1);
        AddArgument("Arg2", 0, UINT8_MAX, &mRequest.arg2);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestEnumsRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedShort:chip::to_underlying(mRequest.arg1)];
        params.arg2 = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg2)];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testEnumsRequestWithParams:params
                                     completion:^(MTRTestClusterClusterTestEnumsResponseParams * _Nullable values,
                                         NSError * _Nullable error) {
                                         NSLog(@"Values: %@", values);
                                         responsesNeeded--;
                                         if (error != nil) {
                                             mError = error;
                                             LogNSError("Error", error);
                                         }
                                         if (responsesNeeded == 0) {
                                             SetCommandExitStatus(mError);
                                         }
                                     }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestEnumsRequest::Type mRequest;
};

/*
 * Command TestNullableOptionalRequest
 */
class TestClusterTestNullableOptionalRequest : public ClusterCommand {
public:
    TestClusterTestNullableOptionalRequest()
        : ClusterCommand("test-nullable-optional-request")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestNullableOptionalRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.arg1.HasValue()) {
            if (mRequest.arg1.Value().IsNull()) {
                params.arg1 = nil;
            } else {
                params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1.Value().Value()];
            }
        } else {
            params.arg1 = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testNullableOptionalRequestWithParams:params
                                           completion:^(MTRTestClusterClusterTestNullableOptionalResponseParams * _Nullable values,
                                               NSError * _Nullable error) {
                                               NSLog(@"Values: %@", values);
                                               responsesNeeded--;
                                               if (error != nil) {
                                                   mError = error;
                                                   LogNSError("Error", error);
                                               }
                                               if (responsesNeeded == 0) {
                                                   SetCommandExitStatus(mError);
                                               }
                                           }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestNullableOptionalRequest::Type mRequest;
};

/*
 * Command TestComplexNullableOptionalRequest
 */
class TestClusterTestComplexNullableOptionalRequest : public ClusterCommand {
public:
    TestClusterTestComplexNullableOptionalRequest()
        : ClusterCommand("test-complex-nullable-optional-request")
        , mComplex_NullableStruct(&mRequest.nullableStruct)
        , mComplex_OptionalStruct(&mRequest.optionalStruct)
        , mComplex_NullableOptionalStruct(&mRequest.nullableOptionalStruct)
        , mComplex_NullableList(&mRequest.nullableList)
        , mComplex_OptionalList(&mRequest.optionalList)
        , mComplex_NullableOptionalList(&mRequest.nullableOptionalList)
    {
        AddArgument("NullableInt", 0, UINT16_MAX, &mRequest.nullableInt);
        AddArgument("OptionalInt", 0, UINT16_MAX, &mRequest.optionalInt);
        AddArgument("NullableOptionalInt", 0, UINT16_MAX, &mRequest.nullableOptionalInt);
        AddArgument("NullableString", &mRequest.nullableString);
        AddArgument("OptionalString", &mRequest.optionalString);
        AddArgument("NullableOptionalString", &mRequest.nullableOptionalString);
        AddArgument("NullableStruct", &mComplex_NullableStruct);
        AddArgument("OptionalStruct", &mComplex_OptionalStruct);
        AddArgument("NullableOptionalStruct", &mComplex_NullableOptionalStruct);
        AddArgument("NullableList", &mComplex_NullableList);
        AddArgument("OptionalList", &mComplex_OptionalList);
        AddArgument("NullableOptionalList", &mComplex_NullableOptionalList);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestComplexNullableOptionalRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.nullableInt.IsNull()) {
            params.nullableInt = nil;
        } else {
            params.nullableInt = [NSNumber numberWithUnsignedShort:mRequest.nullableInt.Value()];
        }
        if (mRequest.optionalInt.HasValue()) {
            params.optionalInt = [NSNumber numberWithUnsignedShort:mRequest.optionalInt.Value()];
        } else {
            params.optionalInt = nil;
        }
        if (mRequest.nullableOptionalInt.HasValue()) {
            if (mRequest.nullableOptionalInt.Value().IsNull()) {
                params.nullableOptionalInt = nil;
            } else {
                params.nullableOptionalInt = [NSNumber numberWithUnsignedShort:mRequest.nullableOptionalInt.Value().Value()];
            }
        } else {
            params.nullableOptionalInt = nil;
        }
        if (mRequest.nullableString.IsNull()) {
            params.nullableString = nil;
        } else {
            params.nullableString = [[NSString alloc] initWithBytes:mRequest.nullableString.Value().data()
                                                             length:mRequest.nullableString.Value().size()
                                                           encoding:NSUTF8StringEncoding];
        }
        if (mRequest.optionalString.HasValue()) {
            params.optionalString = [[NSString alloc] initWithBytes:mRequest.optionalString.Value().data()
                                                             length:mRequest.optionalString.Value().size()
                                                           encoding:NSUTF8StringEncoding];
        } else {
            params.optionalString = nil;
        }
        if (mRequest.nullableOptionalString.HasValue()) {
            if (mRequest.nullableOptionalString.Value().IsNull()) {
                params.nullableOptionalString = nil;
            } else {
                params.nullableOptionalString =
                    [[NSString alloc] initWithBytes:mRequest.nullableOptionalString.Value().Value().data()
                                             length:mRequest.nullableOptionalString.Value().Value().size()
                                           encoding:NSUTF8StringEncoding];
            }
        } else {
            params.nullableOptionalString = nil;
        }
        if (mRequest.nullableStruct.IsNull()) {
            params.nullableStruct = nil;
        } else {
            params.nullableStruct = [MTRTestClusterClusterSimpleStruct new];
            params.nullableStruct.a = [NSNumber numberWithUnsignedChar:mRequest.nullableStruct.Value().a];
            params.nullableStruct.b = [NSNumber numberWithBool:mRequest.nullableStruct.Value().b];
            params.nullableStruct.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.nullableStruct.Value().c)];
            params.nullableStruct.d = [NSData dataWithBytes:mRequest.nullableStruct.Value().d.data()
                                                     length:mRequest.nullableStruct.Value().d.size()];
            params.nullableStruct.e = [[NSString alloc] initWithBytes:mRequest.nullableStruct.Value().e.data()
                                                               length:mRequest.nullableStruct.Value().e.size()
                                                             encoding:NSUTF8StringEncoding];
            params.nullableStruct.f = [NSNumber numberWithUnsignedChar:mRequest.nullableStruct.Value().f.Raw()];
            params.nullableStruct.g = [NSNumber numberWithFloat:mRequest.nullableStruct.Value().g];
            params.nullableStruct.h = [NSNumber numberWithDouble:mRequest.nullableStruct.Value().h];
        }
        if (mRequest.optionalStruct.HasValue()) {
            params.optionalStruct = [MTRTestClusterClusterSimpleStruct new];
            params.optionalStruct.a = [NSNumber numberWithUnsignedChar:mRequest.optionalStruct.Value().a];
            params.optionalStruct.b = [NSNumber numberWithBool:mRequest.optionalStruct.Value().b];
            params.optionalStruct.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.optionalStruct.Value().c)];
            params.optionalStruct.d = [NSData dataWithBytes:mRequest.optionalStruct.Value().d.data()
                                                     length:mRequest.optionalStruct.Value().d.size()];
            params.optionalStruct.e = [[NSString alloc] initWithBytes:mRequest.optionalStruct.Value().e.data()
                                                               length:mRequest.optionalStruct.Value().e.size()
                                                             encoding:NSUTF8StringEncoding];
            params.optionalStruct.f = [NSNumber numberWithUnsignedChar:mRequest.optionalStruct.Value().f.Raw()];
            params.optionalStruct.g = [NSNumber numberWithFloat:mRequest.optionalStruct.Value().g];
            params.optionalStruct.h = [NSNumber numberWithDouble:mRequest.optionalStruct.Value().h];
        } else {
            params.optionalStruct = nil;
        }
        if (mRequest.nullableOptionalStruct.HasValue()) {
            if (mRequest.nullableOptionalStruct.Value().IsNull()) {
                params.nullableOptionalStruct = nil;
            } else {
                params.nullableOptionalStruct = [MTRTestClusterClusterSimpleStruct new];
                params.nullableOptionalStruct.a =
                    [NSNumber numberWithUnsignedChar:mRequest.nullableOptionalStruct.Value().Value().a];
                params.nullableOptionalStruct.b = [NSNumber numberWithBool:mRequest.nullableOptionalStruct.Value().Value().b];
                params.nullableOptionalStruct.c =
                    [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.nullableOptionalStruct.Value().Value().c)];
                params.nullableOptionalStruct.d = [NSData dataWithBytes:mRequest.nullableOptionalStruct.Value().Value().d.data()
                                                                 length:mRequest.nullableOptionalStruct.Value().Value().d.size()];
                params.nullableOptionalStruct.e =
                    [[NSString alloc] initWithBytes:mRequest.nullableOptionalStruct.Value().Value().e.data()
                                             length:mRequest.nullableOptionalStruct.Value().Value().e.size()
                                           encoding:NSUTF8StringEncoding];
                params.nullableOptionalStruct.f =
                    [NSNumber numberWithUnsignedChar:mRequest.nullableOptionalStruct.Value().Value().f.Raw()];
                params.nullableOptionalStruct.g = [NSNumber numberWithFloat:mRequest.nullableOptionalStruct.Value().Value().g];
                params.nullableOptionalStruct.h = [NSNumber numberWithDouble:mRequest.nullableOptionalStruct.Value().Value().h];
            }
        } else {
            params.nullableOptionalStruct = nil;
        }
        if (mRequest.nullableList.IsNull()) {
            params.nullableList = nil;
        } else {
            { // Scope for our temporary variables
                auto * array_1 = [NSMutableArray new];
                for (auto & entry_1 : mRequest.nullableList.Value()) {
                    NSNumber * newElement_1;
                    newElement_1 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1)];
                    [array_1 addObject:newElement_1];
                }
                params.nullableList = array_1;
            }
        }
        if (mRequest.optionalList.HasValue()) {
            { // Scope for our temporary variables
                auto * array_1 = [NSMutableArray new];
                for (auto & entry_1 : mRequest.optionalList.Value()) {
                    NSNumber * newElement_1;
                    newElement_1 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_1)];
                    [array_1 addObject:newElement_1];
                }
                params.optionalList = array_1;
            }
        } else {
            params.optionalList = nil;
        }
        if (mRequest.nullableOptionalList.HasValue()) {
            if (mRequest.nullableOptionalList.Value().IsNull()) {
                params.nullableOptionalList = nil;
            } else {
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : mRequest.nullableOptionalList.Value().Value()) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_2)];
                        [array_2 addObject:newElement_2];
                    }
                    params.nullableOptionalList = array_2;
                }
            }
        } else {
            params.nullableOptionalList = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testComplexNullableOptionalRequestWithParams:params
                                                  completion:^(
                                                      MTRTestClusterClusterTestComplexNullableOptionalResponseParams * _Nullable values,
                                                      NSError * _Nullable error) {
                                                      NSLog(@"Values: %@", values);
                                                      responsesNeeded--;
                                                      if (error != nil) {
                                                          mError = error;
                                                          LogNSError("Error", error);
                                                      }
                                                      if (responsesNeeded == 0) {
                                                          SetCommandExitStatus(mError);
                                                      }
                                                  }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestComplexNullableOptionalRequest::Type mRequest;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>
        mComplex_NullableStruct;
    TypedComplexArgument<chip::Optional<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>> mComplex_OptionalStruct;
    TypedComplexArgument<
        chip::Optional<chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>>>
        mComplex_NullableOptionalStruct;
    TypedComplexArgument<
        chip::app::DataModel::Nullable<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>>>
        mComplex_NullableList;
    TypedComplexArgument<chip::Optional<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>>>
        mComplex_OptionalList;
    TypedComplexArgument<chip::Optional<
        chip::app::DataModel::Nullable<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::SimpleEnum>>>>
        mComplex_NullableOptionalList;
};

/*
 * Command SimpleStructEchoRequest
 */
class TestClusterSimpleStructEchoRequest : public ClusterCommand {
public:
    TestClusterSimpleStructEchoRequest()
        : ClusterCommand("simple-struct-echo-request")
        , mComplex_Arg1(&mRequest.arg1)
    {
        AddArgument("Arg1", &mComplex_Arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterSimpleStructEchoRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [MTRTestClusterClusterSimpleStruct new];
        params.arg1.a = [NSNumber numberWithUnsignedChar:mRequest.arg1.a];
        params.arg1.b = [NSNumber numberWithBool:mRequest.arg1.b];
        params.arg1.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg1.c)];
        params.arg1.d = [NSData dataWithBytes:mRequest.arg1.d.data() length:mRequest.arg1.d.size()];
        params.arg1.e = [[NSString alloc] initWithBytes:mRequest.arg1.e.data()
                                                 length:mRequest.arg1.e.size()
                                               encoding:NSUTF8StringEncoding];
        params.arg1.f = [NSNumber numberWithUnsignedChar:mRequest.arg1.f.Raw()];
        params.arg1.g = [NSNumber numberWithFloat:mRequest.arg1.g];
        params.arg1.h = [NSNumber numberWithDouble:mRequest.arg1.h];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster simpleStructEchoRequestWithParams:params
                                            completion:^(MTRTestClusterClusterSimpleStructResponseParams * _Nullable values,
                                                NSError * _Nullable error) {
                                                NSLog(@"Values: %@", values);
                                                responsesNeeded--;
                                                if (error != nil) {
                                                    mError = error;
                                                    LogNSError("Error", error);
                                                }
                                                if (responsesNeeded == 0) {
                                                    SetCommandExitStatus(mError);
                                                }
                                            }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::SimpleStructEchoRequest::Type mRequest;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mComplex_Arg1;
};

/*
 * Command TimedInvokeRequest
 */
class TestClusterTimedInvokeRequest : public ClusterCommand {
public:
    TestClusterTimedInvokeRequest()
        : ClusterCommand("timed-invoke-request")
    {
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTimedInvokeRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster timedInvokeRequestWithParams:params
                                       completion:^(NSError * _Nullable error) {
                                           responsesNeeded--;
                                           if (error != nil) {
                                               mError = error;
                                               LogNSError("Error", error);
                                           }
                                           if (responsesNeeded == 0) {
                                               SetCommandExitStatus(mError);
                                           }
                                       }];
        }
        return CHIP_NO_ERROR;
    }

private:
};

/*
 * Command TestSimpleOptionalArgumentRequest
 */
class TestClusterTestSimpleOptionalArgumentRequest : public ClusterCommand {
public:
    TestClusterTestSimpleOptionalArgumentRequest()
        : ClusterCommand("test-simple-optional-argument-request")
    {
        AddArgument("Arg1", 0, 1, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestSimpleOptionalArgumentRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        if (mRequest.arg1.HasValue()) {
            params.arg1 = [NSNumber numberWithBool:mRequest.arg1.Value()];
        } else {
            params.arg1 = nil;
        }
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testSimpleOptionalArgumentRequestWithParams:params
                                                      completion:^(NSError * _Nullable error) {
                                                          responsesNeeded--;
                                                          if (error != nil) {
                                                              mError = error;
                                                              LogNSError("Error", error);
                                                          }
                                                          if (responsesNeeded == 0) {
                                                              SetCommandExitStatus(mError);
                                                          }
                                                      }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestSimpleOptionalArgumentRequest::Type mRequest;
};

/*
 * Command TestEmitTestEventRequest
 */
class TestClusterTestEmitTestEventRequest : public ClusterCommand {
public:
    TestClusterTestEmitTestEventRequest()
        : ClusterCommand("test-emit-test-event-request")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        AddArgument("Arg2", 0, UINT8_MAX, &mRequest.arg2);
        AddArgument("Arg3", 0, 1, &mRequest.arg3);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestEmitTestEventRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1];
        params.arg2 = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.arg2)];
        params.arg3 = [NSNumber numberWithBool:mRequest.arg3];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster testEmitTestEventRequestWithParams:params
                                             completion:^(MTRTestClusterClusterTestEmitTestEventResponseParams * _Nullable values,
                                                 NSError * _Nullable error) {
                                                 NSLog(@"Values: %@", values);
                                                 responsesNeeded--;
                                                 if (error != nil) {
                                                     mError = error;
                                                     LogNSError("Error", error);
                                                 }
                                                 if (responsesNeeded == 0) {
                                                     SetCommandExitStatus(mError);
                                                 }
                                             }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestEmitTestEventRequest::Type mRequest;
};

/*
 * Command TestEmitTestFabricScopedEventRequest
 */
class TestClusterTestEmitTestFabricScopedEventRequest : public ClusterCommand {
public:
    TestClusterTestEmitTestFabricScopedEventRequest()
        : ClusterCommand("test-emit-test-fabric-scoped-event-request")
    {
        AddArgument("Arg1", 0, UINT8_MAX, &mRequest.arg1);
        ClusterCommand::AddArguments();
    }

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) command (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        __auto_type * params = [[MTRTestClusterClusterTestEmitTestFabricScopedEventRequestParams alloc] init];
        params.timedInvokeTimeoutMs
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.arg1 = [NSNumber numberWithUnsignedChar:mRequest.arg1];
        uint16_t repeatCount = mRepeatCount.ValueOr(1);
        uint16_t __block responsesNeeded = repeatCount;
        while (repeatCount--) {
            [cluster
                testEmitTestFabricScopedEventRequestWithParams:params
                                                    completion:^(
                                                        MTRTestClusterClusterTestEmitTestFabricScopedEventResponseParams * _Nullable values,
                                                        NSError * _Nullable error) {
                                                        NSLog(@"Values: %@", values);
                                                        responsesNeeded--;
                                                        if (error != nil) {
                                                            mError = error;
                                                            LogNSError("Error", error);
                                                        }
                                                        if (responsesNeeded == 0) {
                                                            SetCommandExitStatus(mError);
                                                        }
                                                    }];
        }
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Commands::TestEmitTestFabricScopedEventRequest::Type mRequest;
};

/*
 * Attribute Boolean
 */
class ReadTestClusterBoolean : public ReadAttribute {
public:
    ReadTestClusterBoolean()
        : ReadAttribute("boolean")
    {
    }

    ~ReadTestClusterBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Boolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Boolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBoolean : public WriteAttribute {
public:
    WriteTestClusterBoolean()
        : WriteAttribute("boolean")
    {
        AddArgument("attr-name", "boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeBooleanWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster Boolean write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBoolean()
        : SubscribeAttribute("boolean")
    {
    }

    ~SubscribeAttributeTestClusterBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Boolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap8
 */
class ReadTestClusterBitmap8 : public ReadAttribute {
public:
    ReadTestClusterBitmap8()
        : ReadAttribute("bitmap8")
    {
    }

    ~ReadTestClusterBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap8 : public WriteAttribute {
public:
    WriteTestClusterBitmap8()
        : WriteAttribute("bitmap8")
    {
        AddArgument("attr-name", "bitmap8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeBitmap8WithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster Bitmap8 write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterBitmap8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap8()
        : SubscribeAttribute("bitmap8")
    {
    }

    ~SubscribeAttributeTestClusterBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBitmap8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap16
 */
class ReadTestClusterBitmap16 : public ReadAttribute {
public:
    ReadTestClusterBitmap16()
        : ReadAttribute("bitmap16")
    {
    }

    ~ReadTestClusterBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap16 : public WriteAttribute {
public:
    WriteTestClusterBitmap16()
        : WriteAttribute("bitmap16")
    {
        AddArgument("attr-name", "bitmap16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeBitmap16WithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster Bitmap16 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterBitmap16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap16()
        : SubscribeAttribute("bitmap16")
    {
    }

    ~SubscribeAttributeTestClusterBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBitmap16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap32
 */
class ReadTestClusterBitmap32 : public ReadAttribute {
public:
    ReadTestClusterBitmap32()
        : ReadAttribute("bitmap32")
    {
    }

    ~ReadTestClusterBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap32WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap32 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap32 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap32 : public WriteAttribute {
public:
    WriteTestClusterBitmap32()
        : WriteAttribute("bitmap32")
    {
        AddArgument("attr-name", "bitmap32");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeBitmap32WithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster Bitmap32 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterBitmap32 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap32()
        : SubscribeAttribute("bitmap32")
    {
    }

    ~SubscribeAttributeTestClusterBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBitmap32WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap32 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Bitmap64
 */
class ReadTestClusterBitmap64 : public ReadAttribute {
public:
    ReadTestClusterBitmap64()
        : ReadAttribute("bitmap64")
    {
    }

    ~ReadTestClusterBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeBitmap64WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Bitmap64 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Bitmap64 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterBitmap64 : public WriteAttribute {
public:
    WriteTestClusterBitmap64()
        : WriteAttribute("bitmap64")
    {
        AddArgument("attr-name", "bitmap64");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeBitmap64WithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster Bitmap64 write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterBitmap64 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterBitmap64()
        : SubscribeAttribute("bitmap64")
    {
    }

    ~SubscribeAttributeTestClusterBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeBitmap64WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Bitmap64 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int8u
 */
class ReadTestClusterInt8u : public ReadAttribute {
public:
    ReadTestClusterInt8u()
        : ReadAttribute("int8u")
    {
    }

    ~ReadTestClusterInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt8u : public WriteAttribute {
public:
    WriteTestClusterInt8u()
        : WriteAttribute("int8u")
    {
        AddArgument("attr-name", "int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeInt8uWithValue:value
                                       params:params
                                   completion:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("TestCluster Int8u write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt8u()
        : SubscribeAttribute("int8u")
    {
    }

    ~SubscribeAttributeTestClusterInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int16u
 */
class ReadTestClusterInt16u : public ReadAttribute {
public:
    ReadTestClusterInt16u()
        : ReadAttribute("int16u")
    {
    }

    ~ReadTestClusterInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt16u : public WriteAttribute {
public:
    WriteTestClusterInt16u()
        : WriteAttribute("int16u")
    {
        AddArgument("attr-name", "int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeInt16uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int16u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt16u()
        : SubscribeAttribute("int16u")
    {
    }

    ~SubscribeAttributeTestClusterInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int24u
 */
class ReadTestClusterInt24u : public ReadAttribute {
public:
    ReadTestClusterInt24u()
        : ReadAttribute("int24u")
    {
    }

    ~ReadTestClusterInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt24uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int24u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int24u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt24u : public WriteAttribute {
public:
    WriteTestClusterInt24u()
        : WriteAttribute("int24u")
    {
        AddArgument("attr-name", "int24u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeInt24uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int24u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterInt24u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt24u()
        : SubscribeAttribute("int24u")
    {
    }

    ~SubscribeAttributeTestClusterInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt24uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int24u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int32u
 */
class ReadTestClusterInt32u : public ReadAttribute {
public:
    ReadTestClusterInt32u()
        : ReadAttribute("int32u")
    {
    }

    ~ReadTestClusterInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt32uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int32u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int32u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt32u : public WriteAttribute {
public:
    WriteTestClusterInt32u()
        : WriteAttribute("int32u")
    {
        AddArgument("attr-name", "int32u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeInt32uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int32u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterInt32u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt32u()
        : SubscribeAttribute("int32u")
    {
    }

    ~SubscribeAttributeTestClusterInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt32uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int32u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int40u
 */
class ReadTestClusterInt40u : public ReadAttribute {
public:
    ReadTestClusterInt40u()
        : ReadAttribute("int40u")
    {
    }

    ~ReadTestClusterInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt40uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int40u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int40u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt40u : public WriteAttribute {
public:
    WriteTestClusterInt40u()
        : WriteAttribute("int40u")
    {
        AddArgument("attr-name", "int40u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt40uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int40u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt40u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt40u()
        : SubscribeAttribute("int40u")
    {
    }

    ~SubscribeAttributeTestClusterInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt40uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int40u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int48u
 */
class ReadTestClusterInt48u : public ReadAttribute {
public:
    ReadTestClusterInt48u()
        : ReadAttribute("int48u")
    {
    }

    ~ReadTestClusterInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt48uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int48u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int48u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt48u : public WriteAttribute {
public:
    WriteTestClusterInt48u()
        : WriteAttribute("int48u")
    {
        AddArgument("attr-name", "int48u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt48uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int48u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt48u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt48u()
        : SubscribeAttribute("int48u")
    {
    }

    ~SubscribeAttributeTestClusterInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt48uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int48u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int56u
 */
class ReadTestClusterInt56u : public ReadAttribute {
public:
    ReadTestClusterInt56u()
        : ReadAttribute("int56u")
    {
    }

    ~ReadTestClusterInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt56uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int56u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int56u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt56u : public WriteAttribute {
public:
    WriteTestClusterInt56u()
        : WriteAttribute("int56u")
    {
        AddArgument("attr-name", "int56u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt56uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int56u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt56u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt56u()
        : SubscribeAttribute("int56u")
    {
    }

    ~SubscribeAttributeTestClusterInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt56uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int56u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int64u
 */
class ReadTestClusterInt64u : public ReadAttribute {
public:
    ReadTestClusterInt64u()
        : ReadAttribute("int64u")
    {
    }

    ~ReadTestClusterInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt64uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int64u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int64u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt64u : public WriteAttribute {
public:
    WriteTestClusterInt64u()
        : WriteAttribute("int64u")
    {
        AddArgument("attr-name", "int64u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeInt64uWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int64u write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterInt64u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt64u()
        : SubscribeAttribute("int64u")
    {
    }

    ~SubscribeAttributeTestClusterInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt64uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int64u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int8s
 */
class ReadTestClusterInt8s : public ReadAttribute {
public:
    ReadTestClusterInt8s()
        : ReadAttribute("int8s")
    {
    }

    ~ReadTestClusterInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt8s : public WriteAttribute {
public:
    WriteTestClusterInt8s()
        : WriteAttribute("int8s")
    {
        AddArgument("attr-name", "int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeInt8sWithValue:value
                                       params:params
                                   completion:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("TestCluster Int8s write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt8s()
        : SubscribeAttribute("int8s")
    {
    }

    ~SubscribeAttributeTestClusterInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int16s
 */
class ReadTestClusterInt16s : public ReadAttribute {
public:
    ReadTestClusterInt16s()
        : ReadAttribute("int16s")
    {
    }

    ~ReadTestClusterInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt16s : public WriteAttribute {
public:
    WriteTestClusterInt16s()
        : WriteAttribute("int16s")
    {
        AddArgument("attr-name", "int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeInt16sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int16s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt16s()
        : SubscribeAttribute("int16s")
    {
    }

    ~SubscribeAttributeTestClusterInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int24s
 */
class ReadTestClusterInt24s : public ReadAttribute {
public:
    ReadTestClusterInt24s()
        : ReadAttribute("int24s")
    {
    }

    ~ReadTestClusterInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000000F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt24sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int24s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int24s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt24s : public WriteAttribute {
public:
    WriteTestClusterInt24s()
        : WriteAttribute("int24s")
    {
        AddArgument("attr-name", "int24s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeInt24sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int24s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterInt24s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt24s()
        : SubscribeAttribute("int24s")
    {
    }

    ~SubscribeAttributeTestClusterInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000000F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt24sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int24s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int32s
 */
class ReadTestClusterInt32s : public ReadAttribute {
public:
    ReadTestClusterInt32s()
        : ReadAttribute("int32s")
    {
    }

    ~ReadTestClusterInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt32sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int32s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int32s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt32s : public WriteAttribute {
public:
    WriteTestClusterInt32s()
        : WriteAttribute("int32s")
    {
        AddArgument("attr-name", "int32s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeInt32sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int32s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterInt32s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt32s()
        : SubscribeAttribute("int32s")
    {
    }

    ~SubscribeAttributeTestClusterInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt32sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int32s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int40s
 */
class ReadTestClusterInt40s : public ReadAttribute {
public:
    ReadTestClusterInt40s()
        : ReadAttribute("int40s")
    {
    }

    ~ReadTestClusterInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt40sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int40s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int40s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt40s : public WriteAttribute {
public:
    WriteTestClusterInt40s()
        : WriteAttribute("int40s")
    {
        AddArgument("attr-name", "int40s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt40sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int40s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt40s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt40s()
        : SubscribeAttribute("int40s")
    {
    }

    ~SubscribeAttributeTestClusterInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt40sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int40s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int48s
 */
class ReadTestClusterInt48s : public ReadAttribute {
public:
    ReadTestClusterInt48s()
        : ReadAttribute("int48s")
    {
    }

    ~ReadTestClusterInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt48sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int48s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int48s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt48s : public WriteAttribute {
public:
    WriteTestClusterInt48s()
        : WriteAttribute("int48s")
    {
        AddArgument("attr-name", "int48s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt48sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int48s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt48s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt48s()
        : SubscribeAttribute("int48s")
    {
    }

    ~SubscribeAttributeTestClusterInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt48sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int48s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int56s
 */
class ReadTestClusterInt56s : public ReadAttribute {
public:
    ReadTestClusterInt56s()
        : ReadAttribute("int56s")
    {
    }

    ~ReadTestClusterInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt56sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int56s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int56s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt56s : public WriteAttribute {
public:
    WriteTestClusterInt56s()
        : WriteAttribute("int56s")
    {
        AddArgument("attr-name", "int56s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt56sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int56s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt56s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt56s()
        : SubscribeAttribute("int56s")
    {
    }

    ~SubscribeAttributeTestClusterInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt56sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int56s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Int64s
 */
class ReadTestClusterInt64s : public ReadAttribute {
public:
    ReadTestClusterInt64s()
        : ReadAttribute("int64s")
    {
    }

    ~ReadTestClusterInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeInt64sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Int64s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Int64s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterInt64s : public WriteAttribute {
public:
    WriteTestClusterInt64s()
        : WriteAttribute("int64s")
    {
        AddArgument("attr-name", "int64s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeInt64sWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Int64s write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterInt64s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterInt64s()
        : SubscribeAttribute("int64s")
    {
    }

    ~SubscribeAttributeTestClusterInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeInt64sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Int64s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Enum8
 */
class ReadTestClusterEnum8 : public ReadAttribute {
public:
    ReadTestClusterEnum8()
        : ReadAttribute("enum8")
    {
    }

    ~ReadTestClusterEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeEnum8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Enum8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Enum8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEnum8 : public WriteAttribute {
public:
    WriteTestClusterEnum8()
        : WriteAttribute("enum8")
    {
        AddArgument("attr-name", "enum8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEnum8WithValue:value
                                       params:params
                                   completion:^(NSError * _Nullable error) {
                                       if (error != nil) {
                                           LogNSError("TestCluster Enum8 write Error", error);
                                       }
                                       SetCommandExitStatus(error);
                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterEnum8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEnum8()
        : SubscribeAttribute("enum8")
    {
    }

    ~SubscribeAttributeTestClusterEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnum8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Enum8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Enum16
 */
class ReadTestClusterEnum16 : public ReadAttribute {
public:
    ReadTestClusterEnum16()
        : ReadAttribute("enum16")
    {
    }

    ~ReadTestClusterEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeEnum16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Enum16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Enum16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEnum16 : public WriteAttribute {
public:
    WriteTestClusterEnum16()
        : WriteAttribute("enum16")
    {
        AddArgument("attr-name", "enum16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeEnum16WithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster Enum16 write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterEnum16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEnum16()
        : SubscribeAttribute("enum16")
    {
    }

    ~SubscribeAttributeTestClusterEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnum16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Enum16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FloatSingle
 */
class ReadTestClusterFloatSingle : public ReadAttribute {
public:
    ReadTestClusterFloatSingle()
        : ReadAttribute("float-single")
    {
    }

    ~ReadTestClusterFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeFloatSingleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.FloatSingle response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster FloatSingle read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterFloatSingle : public WriteAttribute {
public:
    WriteTestClusterFloatSingle()
        : WriteAttribute("float-single")
    {
        AddArgument("attr-name", "float-single");
        AddArgument("attr-value", -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithFloat:mValue];

        [cluster writeAttributeFloatSingleWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("TestCluster FloatSingle write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    float mValue;
};

class SubscribeAttributeTestClusterFloatSingle : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterFloatSingle()
        : SubscribeAttribute("float-single")
    {
    }

    ~SubscribeAttributeTestClusterFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFloatSingleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.FloatSingle response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FloatDouble
 */
class ReadTestClusterFloatDouble : public ReadAttribute {
public:
    ReadTestClusterFloatDouble()
        : ReadAttribute("float-double")
    {
    }

    ~ReadTestClusterFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeFloatDoubleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.FloatDouble response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster FloatDouble read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterFloatDouble : public WriteAttribute {
public:
    WriteTestClusterFloatDouble()
        : WriteAttribute("float-double")
    {
        AddArgument("attr-name", "float-double");
        AddArgument("attr-value", -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithDouble:mValue];

        [cluster writeAttributeFloatDoubleWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("TestCluster FloatDouble write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    double mValue;
};

class SubscribeAttributeTestClusterFloatDouble : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterFloatDouble()
        : SubscribeAttribute("float-double")
    {
    }

    ~SubscribeAttributeTestClusterFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFloatDoubleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.FloatDouble response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute OctetString
 */
class ReadTestClusterOctetString : public ReadAttribute {
public:
    ReadTestClusterOctetString()
        : ReadAttribute("octet-string")
    {
    }

    ~ReadTestClusterOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeOctetStringWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.OctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster OctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterOctetString : public WriteAttribute {
public:
    WriteTestClusterOctetString()
        : WriteAttribute("octet-string")
    {
        AddArgument("attr-name", "octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nonnull value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeOctetStringWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("TestCluster OctetString write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterOctetString()
        : SubscribeAttribute("octet-string")
    {
    }

    ~SubscribeAttributeTestClusterOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.OctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListInt8u
 */
class ReadTestClusterListInt8u : public ReadAttribute {
public:
    ReadTestClusterListInt8u()
        : ReadAttribute("list-int8u")
    {
    }

    ~ReadTestClusterListInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeListInt8uWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListInt8u : public WriteAttribute {
public:
    WriteTestClusterListInt8u()
        : WriteAttribute("list-int8u")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-int8u");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * 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:entry_0];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListInt8uWithValue:value
                                           params:params
                                       completion:^(NSError * _Nullable error) {
                                           if (error != nil) {
                                               LogNSError("TestCluster ListInt8u write Error", error);
                                           }
                                           SetCommandExitStatus(error);
                                       }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const uint8_t> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const uint8_t>> mComplex;
};

class SubscribeAttributeTestClusterListInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListInt8u()
        : SubscribeAttribute("list-int8u")
    {
    }

    ~SubscribeAttributeTestClusterListInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeListInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListOctetString
 */
class ReadTestClusterListOctetString : public ReadAttribute {
public:
    ReadTestClusterListOctetString()
        : ReadAttribute("list-octet-string")
    {
    }

    ~ReadTestClusterListOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeListOctetStringWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListOctetString : public WriteAttribute {
public:
    WriteTestClusterListOctetString()
        : WriteAttribute("list-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * 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) {
                NSData * newElement_0;
                newElement_0 = [NSData dataWithBytes:entry_0.data() length:entry_0.size()];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListOctetStringWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("TestCluster ListOctetString write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::ByteSpan> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::ByteSpan>> mComplex;
};

class SubscribeAttributeTestClusterListOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListOctetString()
        : SubscribeAttribute("list-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterListOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeListOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListStructOctetString
 */
class ReadTestClusterListStructOctetString : public ReadAttribute {
public:
    ReadTestClusterListStructOctetString()
        : ReadAttribute("list-struct-octet-string")
    {
    }

    ~ReadTestClusterListStructOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeListStructOctetStringWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListStructOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListStructOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListStructOctetString : public WriteAttribute {
public:
    WriteTestClusterListStructOctetString()
        : WriteAttribute("list-struct-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-struct-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListStructOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRTestClusterClusterTestListStructOctet * newElement_0;
                newElement_0 = [MTRTestClusterClusterTestListStructOctet new];
                newElement_0.member1 = [NSNumber numberWithUnsignedLongLong:entry_0.member1];
                newElement_0.member2 = [NSData dataWithBytes:entry_0.member2.data() length:entry_0.member2.size()];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListStructOctetStringWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("TestCluster ListStructOctetString write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestListStructOctet::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestListStructOctet::Type>>
        mComplex;
};

class SubscribeAttributeTestClusterListStructOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListStructOctetString()
        : SubscribeAttribute("list-struct-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterListStructOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeListStructOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListStructOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LongOctetString
 */
class ReadTestClusterLongOctetString : public ReadAttribute {
public:
    ReadTestClusterLongOctetString()
        : ReadAttribute("long-octet-string")
    {
    }

    ~ReadTestClusterLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeLongOctetStringWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.LongOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster LongOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterLongOctetString : public WriteAttribute {
public:
    WriteTestClusterLongOctetString()
        : WriteAttribute("long-octet-string")
    {
        AddArgument("attr-name", "long-octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nonnull value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeLongOctetStringWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("TestCluster LongOctetString write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterLongOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterLongOctetString()
        : SubscribeAttribute("long-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLongOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.LongOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute CharString
 */
class ReadTestClusterCharString : public ReadAttribute {
public:
    ReadTestClusterCharString()
        : ReadAttribute("char-string")
    {
    }

    ~ReadTestClusterCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.CharString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster CharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterCharString : public WriteAttribute {
public:
    WriteTestClusterCharString()
        : WriteAttribute("char-string")
    {
        AddArgument("attr-name", "char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeCharStringWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("TestCluster CharString write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterCharString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterCharString()
        : SubscribeAttribute("char-string")
    {
    }

    ~SubscribeAttributeTestClusterCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeCharStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.CharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute LongCharString
 */
class ReadTestClusterLongCharString : public ReadAttribute {
public:
    ReadTestClusterLongCharString()
        : ReadAttribute("long-char-string")
    {
    }

    ~ReadTestClusterLongCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000001F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeLongCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.LongCharString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster LongCharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterLongCharString : public WriteAttribute {
public:
    WriteTestClusterLongCharString()
        : WriteAttribute("long-char-string")
    {
        AddArgument("attr-name", "long-char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterLongCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000001F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nonnull value = [[NSString alloc] initWithBytes:mValue.data()
                                                             length:mValue.size()
                                                           encoding:NSUTF8StringEncoding];

        [cluster writeAttributeLongCharStringWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster LongCharString write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterLongCharString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterLongCharString()
        : SubscribeAttribute("long-char-string")
    {
    }

    ~SubscribeAttributeTestClusterLongCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000001F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeLongCharStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.LongCharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EpochUs
 */
class ReadTestClusterEpochUs : public ReadAttribute {
public:
    ReadTestClusterEpochUs()
        : ReadAttribute("epoch-us")
    {
    }

    ~ReadTestClusterEpochUs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000020) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeEpochUsWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.EpochUs response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster EpochUs read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEpochUs : public WriteAttribute {
public:
    WriteTestClusterEpochUs()
        : WriteAttribute("epoch-us")
    {
        AddArgument("attr-name", "epoch-us");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEpochUs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeEpochUsWithValue:value
                                         params:params
                                     completion:^(NSError * _Nullable error) {
                                         if (error != nil) {
                                             LogNSError("TestCluster EpochUs write Error", error);
                                         }
                                         SetCommandExitStatus(error);
                                     }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterEpochUs : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEpochUs()
        : SubscribeAttribute("epoch-us")
    {
    }

    ~SubscribeAttributeTestClusterEpochUs() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000020) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEpochUsWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.EpochUs response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EpochS
 */
class ReadTestClusterEpochS : public ReadAttribute {
public:
    ReadTestClusterEpochS()
        : ReadAttribute("epoch-s")
    {
    }

    ~ReadTestClusterEpochS() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000021) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeEpochSWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.EpochS response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster EpochS read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEpochS : public WriteAttribute {
public:
    WriteTestClusterEpochS()
        : WriteAttribute("epoch-s")
    {
        AddArgument("attr-name", "epoch-s");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEpochS() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeEpochSWithValue:value
                                        params:params
                                    completion:^(NSError * _Nullable error) {
                                        if (error != nil) {
                                            LogNSError("TestCluster EpochS write Error", error);
                                        }
                                        SetCommandExitStatus(error);
                                    }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterEpochS : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEpochS()
        : SubscribeAttribute("epoch-s")
    {
    }

    ~SubscribeAttributeTestClusterEpochS() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000021) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEpochSWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.EpochS response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute VendorId
 */
class ReadTestClusterVendorId : public ReadAttribute {
public:
    ReadTestClusterVendorId()
        : ReadAttribute("vendor-id")
    {
    }

    ~ReadTestClusterVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000022) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeVendorIdWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.VendorId response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster VendorId read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterVendorId : public WriteAttribute {
public:
    WriteTestClusterVendorId()
        : WriteAttribute("vendor-id")
    {
        AddArgument("attr-name", "vendor-id");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeVendorIdWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster VendorId write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    chip::VendorId mValue;
};

class SubscribeAttributeTestClusterVendorId : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterVendorId()
        : SubscribeAttribute("vendor-id")
    {
    }

    ~SubscribeAttributeTestClusterVendorId() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000022) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeVendorIdWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.VendorId response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListNullablesAndOptionalsStruct
 */
class ReadTestClusterListNullablesAndOptionalsStruct : public ReadAttribute {
public:
    ReadTestClusterListNullablesAndOptionalsStruct()
        : ReadAttribute("list-nullables-and-optionals-struct")
    {
    }

    ~ReadTestClusterListNullablesAndOptionalsStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000023) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster
            readAttributeListNullablesAndOptionalsStructWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListNullablesAndOptionalsStruct response %@", [value description]);
                if (error != nil) {
                    LogNSError("TestCluster ListNullablesAndOptionalsStruct read Error", error);
                }
                SetCommandExitStatus(error);
            }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListNullablesAndOptionalsStruct : public WriteAttribute {
public:
    WriteTestClusterListNullablesAndOptionalsStruct()
        : WriteAttribute("list-nullables-and-optionals-struct")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-nullables-and-optionals-struct");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListNullablesAndOptionalsStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRTestClusterClusterNullablesAndOptionalsStruct * newElement_0;
                newElement_0 = [MTRTestClusterClusterNullablesAndOptionalsStruct new];
                if (entry_0.nullableInt.IsNull()) {
                    newElement_0.nullableInt = nil;
                } else {
                    newElement_0.nullableInt = [NSNumber numberWithUnsignedShort:entry_0.nullableInt.Value()];
                }
                if (entry_0.optionalInt.HasValue()) {
                    newElement_0.optionalInt = [NSNumber numberWithUnsignedShort:entry_0.optionalInt.Value()];
                } else {
                    newElement_0.optionalInt = nil;
                }
                if (entry_0.nullableOptionalInt.HasValue()) {
                    if (entry_0.nullableOptionalInt.Value().IsNull()) {
                        newElement_0.nullableOptionalInt = nil;
                    } else {
                        newElement_0.nullableOptionalInt =
                            [NSNumber numberWithUnsignedShort:entry_0.nullableOptionalInt.Value().Value()];
                    }
                } else {
                    newElement_0.nullableOptionalInt = nil;
                }
                if (entry_0.nullableString.IsNull()) {
                    newElement_0.nullableString = nil;
                } else {
                    newElement_0.nullableString = [[NSString alloc] initWithBytes:entry_0.nullableString.Value().data()
                                                                           length:entry_0.nullableString.Value().size()
                                                                         encoding:NSUTF8StringEncoding];
                }
                if (entry_0.optionalString.HasValue()) {
                    newElement_0.optionalString = [[NSString alloc] initWithBytes:entry_0.optionalString.Value().data()
                                                                           length:entry_0.optionalString.Value().size()
                                                                         encoding:NSUTF8StringEncoding];
                } else {
                    newElement_0.optionalString = nil;
                }
                if (entry_0.nullableOptionalString.HasValue()) {
                    if (entry_0.nullableOptionalString.Value().IsNull()) {
                        newElement_0.nullableOptionalString = nil;
                    } else {
                        newElement_0.nullableOptionalString =
                            [[NSString alloc] initWithBytes:entry_0.nullableOptionalString.Value().Value().data()
                                                     length:entry_0.nullableOptionalString.Value().Value().size()
                                                   encoding:NSUTF8StringEncoding];
                    }
                } else {
                    newElement_0.nullableOptionalString = nil;
                }
                if (entry_0.nullableStruct.IsNull()) {
                    newElement_0.nullableStruct = nil;
                } else {
                    newElement_0.nullableStruct = [MTRTestClusterClusterSimpleStruct new];
                    newElement_0.nullableStruct.a = [NSNumber numberWithUnsignedChar:entry_0.nullableStruct.Value().a];
                    newElement_0.nullableStruct.b = [NSNumber numberWithBool:entry_0.nullableStruct.Value().b];
                    newElement_0.nullableStruct.c =
                        [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.nullableStruct.Value().c)];
                    newElement_0.nullableStruct.d = [NSData dataWithBytes:entry_0.nullableStruct.Value().d.data()
                                                                   length:entry_0.nullableStruct.Value().d.size()];
                    newElement_0.nullableStruct.e = [[NSString alloc] initWithBytes:entry_0.nullableStruct.Value().e.data()
                                                                             length:entry_0.nullableStruct.Value().e.size()
                                                                           encoding:NSUTF8StringEncoding];
                    newElement_0.nullableStruct.f = [NSNumber numberWithUnsignedChar:entry_0.nullableStruct.Value().f.Raw()];
                    newElement_0.nullableStruct.g = [NSNumber numberWithFloat:entry_0.nullableStruct.Value().g];
                    newElement_0.nullableStruct.h = [NSNumber numberWithDouble:entry_0.nullableStruct.Value().h];
                }
                if (entry_0.optionalStruct.HasValue()) {
                    newElement_0.optionalStruct = [MTRTestClusterClusterSimpleStruct new];
                    newElement_0.optionalStruct.a = [NSNumber numberWithUnsignedChar:entry_0.optionalStruct.Value().a];
                    newElement_0.optionalStruct.b = [NSNumber numberWithBool:entry_0.optionalStruct.Value().b];
                    newElement_0.optionalStruct.c =
                        [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.optionalStruct.Value().c)];
                    newElement_0.optionalStruct.d = [NSData dataWithBytes:entry_0.optionalStruct.Value().d.data()
                                                                   length:entry_0.optionalStruct.Value().d.size()];
                    newElement_0.optionalStruct.e = [[NSString alloc] initWithBytes:entry_0.optionalStruct.Value().e.data()
                                                                             length:entry_0.optionalStruct.Value().e.size()
                                                                           encoding:NSUTF8StringEncoding];
                    newElement_0.optionalStruct.f = [NSNumber numberWithUnsignedChar:entry_0.optionalStruct.Value().f.Raw()];
                    newElement_0.optionalStruct.g = [NSNumber numberWithFloat:entry_0.optionalStruct.Value().g];
                    newElement_0.optionalStruct.h = [NSNumber numberWithDouble:entry_0.optionalStruct.Value().h];
                } else {
                    newElement_0.optionalStruct = nil;
                }
                if (entry_0.nullableOptionalStruct.HasValue()) {
                    if (entry_0.nullableOptionalStruct.Value().IsNull()) {
                        newElement_0.nullableOptionalStruct = nil;
                    } else {
                        newElement_0.nullableOptionalStruct = [MTRTestClusterClusterSimpleStruct new];
                        newElement_0.nullableOptionalStruct.a =
                            [NSNumber numberWithUnsignedChar:entry_0.nullableOptionalStruct.Value().Value().a];
                        newElement_0.nullableOptionalStruct.b =
                            [NSNumber numberWithBool:entry_0.nullableOptionalStruct.Value().Value().b];
                        newElement_0.nullableOptionalStruct.c =
                            [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.nullableOptionalStruct.Value().Value().c)];
                        newElement_0.nullableOptionalStruct.d =
                            [NSData dataWithBytes:entry_0.nullableOptionalStruct.Value().Value().d.data()
                                           length:entry_0.nullableOptionalStruct.Value().Value().d.size()];
                        newElement_0.nullableOptionalStruct.e =
                            [[NSString alloc] initWithBytes:entry_0.nullableOptionalStruct.Value().Value().e.data()
                                                     length:entry_0.nullableOptionalStruct.Value().Value().e.size()
                                                   encoding:NSUTF8StringEncoding];
                        newElement_0.nullableOptionalStruct.f =
                            [NSNumber numberWithUnsignedChar:entry_0.nullableOptionalStruct.Value().Value().f.Raw()];
                        newElement_0.nullableOptionalStruct.g =
                            [NSNumber numberWithFloat:entry_0.nullableOptionalStruct.Value().Value().g];
                        newElement_0.nullableOptionalStruct.h =
                            [NSNumber numberWithDouble:entry_0.nullableOptionalStruct.Value().Value().h];
                    }
                } else {
                    newElement_0.nullableOptionalStruct = nil;
                }
                if (entry_0.nullableList.IsNull()) {
                    newElement_0.nullableList = nil;
                } else {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.nullableList.Value()) {
                            NSNumber * newElement_3;
                            newElement_3 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_3)];
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.nullableList = array_3;
                    }
                }
                if (entry_0.optionalList.HasValue()) {
                    { // Scope for our temporary variables
                        auto * array_3 = [NSMutableArray new];
                        for (auto & entry_3 : entry_0.optionalList.Value()) {
                            NSNumber * newElement_3;
                            newElement_3 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_3)];
                            [array_3 addObject:newElement_3];
                        }
                        newElement_0.optionalList = array_3;
                    }
                } else {
                    newElement_0.optionalList = nil;
                }
                if (entry_0.nullableOptionalList.HasValue()) {
                    if (entry_0.nullableOptionalList.Value().IsNull()) {
                        newElement_0.nullableOptionalList = nil;
                    } else {
                        { // Scope for our temporary variables
                            auto * array_4 = [NSMutableArray new];
                            for (auto & entry_4 : entry_0.nullableOptionalList.Value().Value()) {
                                NSNumber * newElement_4;
                                newElement_4 = [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_4)];
                                [array_4 addObject:newElement_4];
                            }
                            newElement_0.nullableOptionalList = array_4;
                        }
                    }
                } else {
                    newElement_0.nullableOptionalList = nil;
                }
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListNullablesAndOptionalsStructWithValue:value
                                                                 params:params
                                                             completion:^(NSError * _Nullable error) {
                                                                 if (error != nil) {
                                                                     LogNSError(
                                                                         "TestCluster ListNullablesAndOptionalsStruct write Error",
                                                                         error);
                                                                 }
                                                                 SetCommandExitStatus(error);
                                                             }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NullablesAndOptionalsStruct::Type> mValue;
    TypedComplexArgument<
        chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::NullablesAndOptionalsStruct::Type>>
        mComplex;
};

class SubscribeAttributeTestClusterListNullablesAndOptionalsStruct : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListNullablesAndOptionalsStruct()
        : SubscribeAttribute("list-nullables-and-optionals-struct")
    {
    }

    ~SubscribeAttributeTestClusterListNullablesAndOptionalsStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000023) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeListNullablesAndOptionalsStructWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListNullablesAndOptionalsStruct response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute EnumAttr
 */
class ReadTestClusterEnumAttr : public ReadAttribute {
public:
    ReadTestClusterEnumAttr()
        : ReadAttribute("enum-attr")
    {
    }

    ~ReadTestClusterEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeEnumAttrWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.EnumAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster EnumAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterEnumAttr : public WriteAttribute {
public:
    WriteTestClusterEnumAttr()
        : WriteAttribute("enum-attr")
    {
        AddArgument("attr-name", "enum-attr");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeEnumAttrWithValue:value
                                          params:params
                                      completion:^(NSError * _Nullable error) {
                                          if (error != nil) {
                                              LogNSError("TestCluster EnumAttr write Error", error);
                                          }
                                          SetCommandExitStatus(error);
                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterEnumAttr : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterEnumAttr()
        : SubscribeAttribute("enum-attr")
    {
    }

    ~SubscribeAttributeTestClusterEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeEnumAttrWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.EnumAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute StructAttr
 */
class ReadTestClusterStructAttr : public ReadAttribute {
public:
    ReadTestClusterStructAttr()
        : ReadAttribute("struct-attr")
    {
    }

    ~ReadTestClusterStructAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeStructAttrWithCompletion:^(
            MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.StructAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster StructAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterStructAttr : public WriteAttribute {
public:
    WriteTestClusterStructAttr()
        : WriteAttribute("struct-attr")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "struct-attr");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterStructAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRTestClusterClusterSimpleStruct * _Nonnull value;
        value = [MTRTestClusterClusterSimpleStruct new];
        value.a = [NSNumber numberWithUnsignedChar:mValue.a];
        value.b = [NSNumber numberWithBool:mValue.b];
        value.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mValue.c)];
        value.d = [NSData dataWithBytes:mValue.d.data() length:mValue.d.size()];
        value.e = [[NSString alloc] initWithBytes:mValue.e.data() length:mValue.e.size() encoding:NSUTF8StringEncoding];
        value.f = [NSNumber numberWithUnsignedChar:mValue.f.Raw()];
        value.g = [NSNumber numberWithFloat:mValue.g];
        value.h = [NSNumber numberWithDouble:mValue.h];

        [cluster writeAttributeStructAttrWithValue:value
                                            params:params
                                        completion:^(NSError * _Nullable error) {
                                            if (error != nil) {
                                                LogNSError("TestCluster StructAttr write Error", error);
                                            }
                                            SetCommandExitStatus(error);
                                        }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type mValue;
    TypedComplexArgument<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mComplex;
};

class SubscribeAttributeTestClusterStructAttr : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterStructAttr()
        : SubscribeAttribute("struct-attr")
    {
    }

    ~SubscribeAttributeTestClusterStructAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeStructAttrWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.StructAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt8u
 */
class ReadTestClusterRangeRestrictedInt8u : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt8u()
        : ReadAttribute("range-restricted-int8u")
    {
    }

    ~ReadTestClusterRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt8u : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt8u()
        : WriteAttribute("range-restricted-int8u")
    {
        AddArgument("attr-name", "range-restricted-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeRangeRestrictedInt8uWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("TestCluster RangeRestrictedInt8u write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt8u()
        : SubscribeAttribute("range-restricted-int8u")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt8s
 */
class ReadTestClusterRangeRestrictedInt8s : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt8s()
        : ReadAttribute("range-restricted-int8s")
    {
    }

    ~ReadTestClusterRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt8s : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt8s()
        : WriteAttribute("range-restricted-int8s")
    {
        AddArgument("attr-name", "range-restricted-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeRangeRestrictedInt8sWithValue:value
                                                      params:params
                                                  completion:^(NSError * _Nullable error) {
                                                      if (error != nil) {
                                                          LogNSError("TestCluster RangeRestrictedInt8s write Error", error);
                                                      }
                                                      SetCommandExitStatus(error);
                                                  }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt8s()
        : SubscribeAttribute("range-restricted-int8s")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt16u
 */
class ReadTestClusterRangeRestrictedInt16u : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt16u()
        : ReadAttribute("range-restricted-int16u")
    {
    }

    ~ReadTestClusterRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt16u : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt16u()
        : WriteAttribute("range-restricted-int16u")
    {
        AddArgument("attr-name", "range-restricted-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeRangeRestrictedInt16uWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("TestCluster RangeRestrictedInt16u write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt16u()
        : SubscribeAttribute("range-restricted-int16u")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute RangeRestrictedInt16s
 */
class ReadTestClusterRangeRestrictedInt16s : public ReadAttribute {
public:
    ReadTestClusterRangeRestrictedInt16s()
        : ReadAttribute("range-restricted-int16s")
    {
    }

    ~ReadTestClusterRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeRangeRestrictedInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.RangeRestrictedInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster RangeRestrictedInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterRangeRestrictedInt16s : public WriteAttribute {
public:
    WriteTestClusterRangeRestrictedInt16s()
        : WriteAttribute("range-restricted-int16s")
    {
        AddArgument("attr-name", "range-restricted-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeRangeRestrictedInt16sWithValue:value
                                                       params:params
                                                   completion:^(NSError * _Nullable error) {
                                                       if (error != nil) {
                                                           LogNSError("TestCluster RangeRestrictedInt16s write Error", error);
                                                       }
                                                       SetCommandExitStatus(error);
                                                   }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterRangeRestrictedInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterRangeRestrictedInt16s()
        : SubscribeAttribute("range-restricted-int16s")
    {
    }

    ~SubscribeAttributeTestClusterRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeRangeRestrictedInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.RangeRestrictedInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListLongOctetString
 */
class ReadTestClusterListLongOctetString : public ReadAttribute {
public:
    ReadTestClusterListLongOctetString()
        : ReadAttribute("list-long-octet-string")
    {
    }

    ~ReadTestClusterListLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000002A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeListLongOctetStringWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ListLongOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ListLongOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListLongOctetString : public WriteAttribute {
public:
    WriteTestClusterListLongOctetString()
        : WriteAttribute("list-long-octet-string")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-long-octet-string");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * 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) {
                NSData * newElement_0;
                newElement_0 = [NSData dataWithBytes:entry_0.data() length:entry_0.size()];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListLongOctetStringWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("TestCluster ListLongOctetString write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::ByteSpan> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::ByteSpan>> mComplex;
};

class SubscribeAttributeTestClusterListLongOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListLongOctetString()
        : SubscribeAttribute("list-long-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterListLongOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000002A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeListLongOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListLongOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ListFabricScoped
 */
class ReadTestClusterListFabricScoped : public ReadAttribute {
public:
    ReadTestClusterListFabricScoped()
        : ReadAttribute("list-fabric-scoped")
    {
    }

    ~ReadTestClusterListFabricScoped() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000002B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRReadParams * params = [[MTRReadParams alloc] init];
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster readAttributeListFabricScopedWithParams:params
                                              completion:^(NSArray * _Nullable value, NSError * _Nullable error) {
                                                  NSLog(@"TestCluster.ListFabricScoped response %@", [value description]);
                                                  if (error != nil) {
                                                      LogNSError("TestCluster ListFabricScoped read Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterListFabricScoped : public WriteAttribute {
public:
    WriteTestClusterListFabricScoped()
        : WriteAttribute("list-fabric-scoped")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "list-fabric-scoped");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterListFabricScoped() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * 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) {
                MTRTestClusterClusterTestFabricScoped * newElement_0;
                newElement_0 = [MTRTestClusterClusterTestFabricScoped new];
                newElement_0.fabricSensitiveInt8u = [NSNumber numberWithUnsignedChar:entry_0.fabricSensitiveInt8u];
                if (entry_0.optionalFabricSensitiveInt8u.HasValue()) {
                    newElement_0.optionalFabricSensitiveInt8u =
                        [NSNumber numberWithUnsignedChar:entry_0.optionalFabricSensitiveInt8u.Value()];
                } else {
                    newElement_0.optionalFabricSensitiveInt8u = nil;
                }
                if (entry_0.nullableFabricSensitiveInt8u.IsNull()) {
                    newElement_0.nullableFabricSensitiveInt8u = nil;
                } else {
                    newElement_0.nullableFabricSensitiveInt8u =
                        [NSNumber numberWithUnsignedChar:entry_0.nullableFabricSensitiveInt8u.Value()];
                }
                if (entry_0.nullableOptionalFabricSensitiveInt8u.HasValue()) {
                    if (entry_0.nullableOptionalFabricSensitiveInt8u.Value().IsNull()) {
                        newElement_0.nullableOptionalFabricSensitiveInt8u = nil;
                    } else {
                        newElement_0.nullableOptionalFabricSensitiveInt8u =
                            [NSNumber numberWithUnsignedChar:entry_0.nullableOptionalFabricSensitiveInt8u.Value().Value()];
                    }
                } else {
                    newElement_0.nullableOptionalFabricSensitiveInt8u = nil;
                }
                newElement_0.fabricSensitiveCharString = [[NSString alloc] initWithBytes:entry_0.fabricSensitiveCharString.data()
                                                                                  length:entry_0.fabricSensitiveCharString.size()
                                                                                encoding:NSUTF8StringEncoding];
                newElement_0.fabricSensitiveStruct = [MTRTestClusterClusterSimpleStruct new];
                newElement_0.fabricSensitiveStruct.a = [NSNumber numberWithUnsignedChar:entry_0.fabricSensitiveStruct.a];
                newElement_0.fabricSensitiveStruct.b = [NSNumber numberWithBool:entry_0.fabricSensitiveStruct.b];
                newElement_0.fabricSensitiveStruct.c =
                    [NSNumber numberWithUnsignedChar:chip::to_underlying(entry_0.fabricSensitiveStruct.c)];
                newElement_0.fabricSensitiveStruct.d = [NSData dataWithBytes:entry_0.fabricSensitiveStruct.d.data()
                                                                      length:entry_0.fabricSensitiveStruct.d.size()];
                newElement_0.fabricSensitiveStruct.e = [[NSString alloc] initWithBytes:entry_0.fabricSensitiveStruct.e.data()
                                                                                length:entry_0.fabricSensitiveStruct.e.size()
                                                                              encoding:NSUTF8StringEncoding];
                newElement_0.fabricSensitiveStruct.f = [NSNumber numberWithUnsignedChar:entry_0.fabricSensitiveStruct.f.Raw()];
                newElement_0.fabricSensitiveStruct.g = [NSNumber numberWithFloat:entry_0.fabricSensitiveStruct.g];
                newElement_0.fabricSensitiveStruct.h = [NSNumber numberWithDouble:entry_0.fabricSensitiveStruct.h];
                { // Scope for our temporary variables
                    auto * array_2 = [NSMutableArray new];
                    for (auto & entry_2 : entry_0.fabricSensitiveInt8uList) {
                        NSNumber * newElement_2;
                        newElement_2 = [NSNumber numberWithUnsignedChar:entry_2];
                        [array_2 addObject:newElement_2];
                    }
                    newElement_0.fabricSensitiveInt8uList = array_2;
                }
                newElement_0.fabricIndex = [NSNumber numberWithUnsignedChar:entry_0.fabricIndex];
                [array_0 addObject:newElement_0];
            }
            value = array_0;
        }

        [cluster writeAttributeListFabricScopedWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster ListFabricScoped write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestFabricScoped::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::List<const chip::app::Clusters::TestCluster::Structs::TestFabricScoped::Type>>
        mComplex;
};

class SubscribeAttributeTestClusterListFabricScoped : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterListFabricScoped()
        : SubscribeAttribute("list-fabric-scoped")
    {
    }

    ~SubscribeAttributeTestClusterListFabricScoped() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000002B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeListFabricScopedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ListFabricScoped response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute TimedWriteBoolean
 */
class ReadTestClusterTimedWriteBoolean : public ReadAttribute {
public:
    ReadTestClusterTimedWriteBoolean()
        : ReadAttribute("timed-write-boolean")
    {
    }

    ~ReadTestClusterTimedWriteBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000030) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeTimedWriteBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.TimedWriteBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster TimedWriteBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterTimedWriteBoolean : public WriteAttribute {
public:
    WriteTestClusterTimedWriteBoolean()
        : WriteAttribute("timed-write-boolean")
    {
        AddArgument("attr-name", "timed-write-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterTimedWriteBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeTimedWriteBooleanWithValue:value
                                                   params:params
                                               completion:^(NSError * _Nullable error) {
                                                   if (error != nil) {
                                                       LogNSError("TestCluster TimedWriteBoolean write Error", error);
                                                   }
                                                   SetCommandExitStatus(error);
                                               }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterTimedWriteBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterTimedWriteBoolean()
        : SubscribeAttribute("timed-write-boolean")
    {
    }

    ~SubscribeAttributeTestClusterTimedWriteBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000030) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeTimedWriteBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.TimedWriteBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneralErrorBoolean
 */
class ReadTestClusterGeneralErrorBoolean : public ReadAttribute {
public:
    ReadTestClusterGeneralErrorBoolean()
        : ReadAttribute("general-error-boolean")
    {
    }

    ~ReadTestClusterGeneralErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000031) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneralErrorBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.GeneralErrorBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster GeneralErrorBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterGeneralErrorBoolean : public WriteAttribute {
public:
    WriteTestClusterGeneralErrorBoolean()
        : WriteAttribute("general-error-boolean")
    {
        AddArgument("attr-name", "general-error-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterGeneralErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeGeneralErrorBooleanWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("TestCluster GeneralErrorBoolean write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterGeneralErrorBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterGeneralErrorBoolean()
        : SubscribeAttribute("general-error-boolean")
    {
    }

    ~SubscribeAttributeTestClusterGeneralErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000031) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneralErrorBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.GeneralErrorBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterErrorBoolean
 */
class ReadTestClusterClusterErrorBoolean : public ReadAttribute {
public:
    ReadTestClusterClusterErrorBoolean()
        : ReadAttribute("cluster-error-boolean")
    {
    }

    ~ReadTestClusterClusterErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00000032) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterErrorBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ClusterErrorBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ClusterErrorBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterClusterErrorBoolean : public WriteAttribute {
public:
    WriteTestClusterClusterErrorBoolean()
        : WriteAttribute("cluster-error-boolean")
    {
        AddArgument("attr-name", "cluster-error-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterClusterErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeClusterErrorBooleanWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("TestCluster ClusterErrorBoolean write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterClusterErrorBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterClusterErrorBoolean()
        : SubscribeAttribute("cluster-error-boolean")
    {
    }

    ~SubscribeAttributeTestClusterClusterErrorBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00000032) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterErrorBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ClusterErrorBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute Unsupported
 */
class ReadTestClusterUnsupported : public ReadAttribute {
public:
    ReadTestClusterUnsupported()
        : ReadAttribute("unsupported")
    {
    }

    ~ReadTestClusterUnsupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x000000FF) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeUnsupportedWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.Unsupported response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster Unsupported read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterUnsupported : public WriteAttribute {
public:
    WriteTestClusterUnsupported()
        : WriteAttribute("unsupported")
    {
        AddArgument("attr-name", "unsupported");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterUnsupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x000000FF) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeUnsupportedWithValue:value
                                             params:params
                                         completion:^(NSError * _Nullable error) {
                                             if (error != nil) {
                                                 LogNSError("TestCluster Unsupported write Error", error);
                                             }
                                             SetCommandExitStatus(error);
                                         }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterUnsupported : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterUnsupported()
        : SubscribeAttribute("unsupported")
    {
    }

    ~SubscribeAttributeTestClusterUnsupported() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x000000FF) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeUnsupportedWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.Unsupported response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBoolean
 */
class ReadTestClusterNullableBoolean : public ReadAttribute {
public:
    ReadTestClusterNullableBoolean()
        : ReadAttribute("nullable-boolean")
    {
    }

    ~ReadTestClusterNullableBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004000) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBooleanWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBoolean response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBoolean read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBoolean : public WriteAttribute {
public:
    WriteTestClusterNullableBoolean()
        : WriteAttribute("nullable-boolean")
    {
        AddArgument("attr-name", "nullable-boolean");
        AddArgument("attr-value", 0, 1, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithBool:mValue];

        [cluster writeAttributeNullableBooleanWithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("TestCluster NullableBoolean write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    bool mValue;
};

class SubscribeAttributeTestClusterNullableBoolean : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBoolean()
        : SubscribeAttribute("nullable-boolean")
    {
    }

    ~SubscribeAttributeTestClusterNullableBoolean() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004000) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableBooleanWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBoolean response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap8
 */
class ReadTestClusterNullableBitmap8 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap8()
        : ReadAttribute("nullable-bitmap8")
    {
    }

    ~ReadTestClusterNullableBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004001) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap8 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap8()
        : WriteAttribute("nullable-bitmap8")
    {
        AddArgument("attr-name", "nullable-bitmap8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableBitmap8WithValue:value
                                                 params:params
                                             completion:^(NSError * _Nullable error) {
                                                 if (error != nil) {
                                                     LogNSError("TestCluster NullableBitmap8 write Error", error);
                                                 }
                                                 SetCommandExitStatus(error);
                                             }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap8()
        : SubscribeAttribute("nullable-bitmap8")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004001) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableBitmap8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap16
 */
class ReadTestClusterNullableBitmap16 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap16()
        : ReadAttribute("nullable-bitmap16")
    {
    }

    ~ReadTestClusterNullableBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004002) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap16 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap16()
        : WriteAttribute("nullable-bitmap16")
    {
        AddArgument("attr-name", "nullable-bitmap16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableBitmap16WithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster NullableBitmap16 write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap16()
        : SubscribeAttribute("nullable-bitmap16")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004002) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableBitmap16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap32
 */
class ReadTestClusterNullableBitmap32 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap32()
        : ReadAttribute("nullable-bitmap32")
    {
    }

    ~ReadTestClusterNullableBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004003) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap32WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap32 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap32 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap32 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap32()
        : WriteAttribute("nullable-bitmap32")
    {
        AddArgument("attr-name", "nullable-bitmap32");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableBitmap32WithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster NullableBitmap32 write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap32 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap32()
        : SubscribeAttribute("nullable-bitmap32")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap32() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004003) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableBitmap32WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap32 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableBitmap64
 */
class ReadTestClusterNullableBitmap64 : public ReadAttribute {
public:
    ReadTestClusterNullableBitmap64()
        : ReadAttribute("nullable-bitmap64")
    {
    }

    ~ReadTestClusterNullableBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004004) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableBitmap64WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableBitmap64 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableBitmap64 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableBitmap64 : public WriteAttribute {
public:
    WriteTestClusterNullableBitmap64()
        : WriteAttribute("nullable-bitmap64")
    {
        AddArgument("attr-name", "nullable-bitmap64");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableBitmap64WithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster NullableBitmap64 write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableBitmap64 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableBitmap64()
        : SubscribeAttribute("nullable-bitmap64")
    {
    }

    ~SubscribeAttributeTestClusterNullableBitmap64() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004004) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableBitmap64WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableBitmap64 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt8u
 */
class ReadTestClusterNullableInt8u : public ReadAttribute {
public:
    ReadTestClusterNullableInt8u()
        : ReadAttribute("nullable-int8u")
    {
    }

    ~ReadTestClusterNullableInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004005) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt8u : public WriteAttribute {
public:
    WriteTestClusterNullableInt8u()
        : WriteAttribute("nullable-int8u")
    {
        AddArgument("attr-name", "nullable-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableInt8uWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("TestCluster NullableInt8u write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt8u()
        : SubscribeAttribute("nullable-int8u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004005) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt16u
 */
class ReadTestClusterNullableInt16u : public ReadAttribute {
public:
    ReadTestClusterNullableInt16u()
        : ReadAttribute("nullable-int16u")
    {
    }

    ~ReadTestClusterNullableInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004006) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt16u : public WriteAttribute {
public:
    WriteTestClusterNullableInt16u()
        : WriteAttribute("nullable-int16u")
    {
        AddArgument("attr-name", "nullable-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableInt16uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt16u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt16u()
        : SubscribeAttribute("nullable-int16u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004006) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt24u
 */
class ReadTestClusterNullableInt24u : public ReadAttribute {
public:
    ReadTestClusterNullableInt24u()
        : ReadAttribute("nullable-int24u")
    {
    }

    ~ReadTestClusterNullableInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004007) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt24uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt24u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt24u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt24u : public WriteAttribute {
public:
    WriteTestClusterNullableInt24u()
        : WriteAttribute("nullable-int24u")
    {
        AddArgument("attr-name", "nullable-int24u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableInt24uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt24u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt24u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt24u()
        : SubscribeAttribute("nullable-int24u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt24u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004007) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt24uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt24u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt32u
 */
class ReadTestClusterNullableInt32u : public ReadAttribute {
public:
    ReadTestClusterNullableInt32u()
        : ReadAttribute("nullable-int32u")
    {
    }

    ~ReadTestClusterNullableInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004008) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt32uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt32u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt32u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt32u : public WriteAttribute {
public:
    WriteTestClusterNullableInt32u()
        : WriteAttribute("nullable-int32u")
    {
        AddArgument("attr-name", "nullable-int32u");
        AddArgument("attr-value", 0, UINT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedInt:mValue];

        [cluster writeAttributeNullableInt32uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt32u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt32u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt32u()
        : SubscribeAttribute("nullable-int32u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt32u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004008) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt32uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt32u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt40u
 */
class ReadTestClusterNullableInt40u : public ReadAttribute {
public:
    ReadTestClusterNullableInt40u()
        : ReadAttribute("nullable-int40u")
    {
    }

    ~ReadTestClusterNullableInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004009) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt40uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt40u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt40u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt40u : public WriteAttribute {
public:
    WriteTestClusterNullableInt40u()
        : WriteAttribute("nullable-int40u")
    {
        AddArgument("attr-name", "nullable-int40u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt40uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt40u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt40u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt40u()
        : SubscribeAttribute("nullable-int40u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt40u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004009) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt40uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt40u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt48u
 */
class ReadTestClusterNullableInt48u : public ReadAttribute {
public:
    ReadTestClusterNullableInt48u()
        : ReadAttribute("nullable-int48u")
    {
    }

    ~ReadTestClusterNullableInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt48uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt48u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt48u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt48u : public WriteAttribute {
public:
    WriteTestClusterNullableInt48u()
        : WriteAttribute("nullable-int48u")
    {
        AddArgument("attr-name", "nullable-int48u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt48uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt48u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt48u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt48u()
        : SubscribeAttribute("nullable-int48u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt48u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt48uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt48u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt56u
 */
class ReadTestClusterNullableInt56u : public ReadAttribute {
public:
    ReadTestClusterNullableInt56u()
        : ReadAttribute("nullable-int56u")
    {
    }

    ~ReadTestClusterNullableInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400B) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt56uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt56u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt56u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt56u : public WriteAttribute {
public:
    WriteTestClusterNullableInt56u()
        : WriteAttribute("nullable-int56u")
    {
        AddArgument("attr-name", "nullable-int56u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt56uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt56u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt56u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt56u()
        : SubscribeAttribute("nullable-int56u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt56u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400B) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt56uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt56u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt64u
 */
class ReadTestClusterNullableInt64u : public ReadAttribute {
public:
    ReadTestClusterNullableInt64u()
        : ReadAttribute("nullable-int64u")
    {
    }

    ~ReadTestClusterNullableInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400C) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt64uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt64u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt64u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt64u : public WriteAttribute {
public:
    WriteTestClusterNullableInt64u()
        : WriteAttribute("nullable-int64u")
    {
        AddArgument("attr-name", "nullable-int64u");
        AddArgument("attr-value", 0, UINT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedLongLong:mValue];

        [cluster writeAttributeNullableInt64uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt64u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt64u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt64u()
        : SubscribeAttribute("nullable-int64u")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt64u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400C) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt64uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt64u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt8s
 */
class ReadTestClusterNullableInt8s : public ReadAttribute {
public:
    ReadTestClusterNullableInt8s()
        : ReadAttribute("nullable-int8s")
    {
    }

    ~ReadTestClusterNullableInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400D) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt8s : public WriteAttribute {
public:
    WriteTestClusterNullableInt8s()
        : WriteAttribute("nullable-int8s")
    {
        AddArgument("attr-name", "nullable-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeNullableInt8sWithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("TestCluster NullableInt8s write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterNullableInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt8s()
        : SubscribeAttribute("nullable-int8s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400D) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt16s
 */
class ReadTestClusterNullableInt16s : public ReadAttribute {
public:
    ReadTestClusterNullableInt16s()
        : ReadAttribute("nullable-int16s")
    {
    }

    ~ReadTestClusterNullableInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt16s : public WriteAttribute {
public:
    WriteTestClusterNullableInt16s()
        : WriteAttribute("nullable-int16s")
    {
        AddArgument("attr-name", "nullable-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithShort:mValue];

        [cluster writeAttributeNullableInt16sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt16s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterNullableInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt16s()
        : SubscribeAttribute("nullable-int16s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt24s
 */
class ReadTestClusterNullableInt24s : public ReadAttribute {
public:
    ReadTestClusterNullableInt24s()
        : ReadAttribute("nullable-int24s")
    {
    }

    ~ReadTestClusterNullableInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000400F) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt24sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt24s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt24s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt24s : public WriteAttribute {
public:
    WriteTestClusterNullableInt24s()
        : WriteAttribute("nullable-int24s")
    {
        AddArgument("attr-name", "nullable-int24s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000400F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeNullableInt24sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt24s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt24s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt24s()
        : SubscribeAttribute("nullable-int24s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt24s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000400F) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt24sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt24s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt32s
 */
class ReadTestClusterNullableInt32s : public ReadAttribute {
public:
    ReadTestClusterNullableInt32s()
        : ReadAttribute("nullable-int32s")
    {
    }

    ~ReadTestClusterNullableInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004010) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt32sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt32s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt32s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt32s : public WriteAttribute {
public:
    WriteTestClusterNullableInt32s()
        : WriteAttribute("nullable-int32s")
    {
        AddArgument("attr-name", "nullable-int32s");
        AddArgument("attr-value", INT32_MIN, INT32_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithInt:mValue];

        [cluster writeAttributeNullableInt32sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt32s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int32_t mValue;
};

class SubscribeAttributeTestClusterNullableInt32s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt32s()
        : SubscribeAttribute("nullable-int32s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt32s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004010) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt32sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt32s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt40s
 */
class ReadTestClusterNullableInt40s : public ReadAttribute {
public:
    ReadTestClusterNullableInt40s()
        : ReadAttribute("nullable-int40s")
    {
    }

    ~ReadTestClusterNullableInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004011) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt40sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt40s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt40s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt40s : public WriteAttribute {
public:
    WriteTestClusterNullableInt40s()
        : WriteAttribute("nullable-int40s")
    {
        AddArgument("attr-name", "nullable-int40s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt40sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt40s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt40s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt40s()
        : SubscribeAttribute("nullable-int40s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt40s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004011) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt40sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt40s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt48s
 */
class ReadTestClusterNullableInt48s : public ReadAttribute {
public:
    ReadTestClusterNullableInt48s()
        : ReadAttribute("nullable-int48s")
    {
    }

    ~ReadTestClusterNullableInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004012) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt48sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt48s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt48s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt48s : public WriteAttribute {
public:
    WriteTestClusterNullableInt48s()
        : WriteAttribute("nullable-int48s")
    {
        AddArgument("attr-name", "nullable-int48s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt48sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt48s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt48s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt48s()
        : SubscribeAttribute("nullable-int48s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt48s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004012) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt48sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt48s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt56s
 */
class ReadTestClusterNullableInt56s : public ReadAttribute {
public:
    ReadTestClusterNullableInt56s()
        : ReadAttribute("nullable-int56s")
    {
    }

    ~ReadTestClusterNullableInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004013) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt56sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt56s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt56s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt56s : public WriteAttribute {
public:
    WriteTestClusterNullableInt56s()
        : WriteAttribute("nullable-int56s")
    {
        AddArgument("attr-name", "nullable-int56s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt56sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt56s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt56s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt56s()
        : SubscribeAttribute("nullable-int56s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt56s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004013) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt56sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt56s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableInt64s
 */
class ReadTestClusterNullableInt64s : public ReadAttribute {
public:
    ReadTestClusterNullableInt64s()
        : ReadAttribute("nullable-int64s")
    {
    }

    ~ReadTestClusterNullableInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004014) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableInt64sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableInt64s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableInt64s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableInt64s : public WriteAttribute {
public:
    WriteTestClusterNullableInt64s()
        : WriteAttribute("nullable-int64s")
    {
        AddArgument("attr-name", "nullable-int64s");
        AddArgument("attr-value", INT64_MIN, INT64_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithLongLong:mValue];

        [cluster writeAttributeNullableInt64sWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableInt64s write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    int64_t mValue;
};

class SubscribeAttributeTestClusterNullableInt64s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableInt64s()
        : SubscribeAttribute("nullable-int64s")
    {
    }

    ~SubscribeAttributeTestClusterNullableInt64s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004014) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableInt64sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableInt64s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnum8
 */
class ReadTestClusterNullableEnum8 : public ReadAttribute {
public:
    ReadTestClusterNullableEnum8()
        : ReadAttribute("nullable-enum8")
    {
    }

    ~ReadTestClusterNullableEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004015) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableEnum8WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableEnum8 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableEnum8 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableEnum8 : public WriteAttribute {
public:
    WriteTestClusterNullableEnum8()
        : WriteAttribute("nullable-enum8")
    {
        AddArgument("attr-name", "nullable-enum8");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableEnum8WithValue:value
                                               params:params
                                           completion:^(NSError * _Nullable error) {
                                               if (error != nil) {
                                                   LogNSError("TestCluster NullableEnum8 write Error", error);
                                               }
                                               SetCommandExitStatus(error);
                                           }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableEnum8 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableEnum8()
        : SubscribeAttribute("nullable-enum8")
    {
    }

    ~SubscribeAttributeTestClusterNullableEnum8() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004015) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableEnum8WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableEnum8 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnum16
 */
class ReadTestClusterNullableEnum16 : public ReadAttribute {
public:
    ReadTestClusterNullableEnum16()
        : ReadAttribute("nullable-enum16")
    {
    }

    ~ReadTestClusterNullableEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004016) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableEnum16WithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableEnum16 response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableEnum16 read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableEnum16 : public WriteAttribute {
public:
    WriteTestClusterNullableEnum16()
        : WriteAttribute("nullable-enum16")
    {
        AddArgument("attr-name", "nullable-enum16");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster writeAttributeNullableEnum16WithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableEnum16 write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableEnum16 : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableEnum16()
        : SubscribeAttribute("nullable-enum16")
    {
    }

    ~SubscribeAttributeTestClusterNullableEnum16() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004016) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableEnum16WithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableEnum16 response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableFloatSingle
 */
class ReadTestClusterNullableFloatSingle : public ReadAttribute {
public:
    ReadTestClusterNullableFloatSingle()
        : ReadAttribute("nullable-float-single")
    {
    }

    ~ReadTestClusterNullableFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004017) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableFloatSingleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableFloatSingle response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableFloatSingle read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableFloatSingle : public WriteAttribute {
public:
    WriteTestClusterNullableFloatSingle()
        : WriteAttribute("nullable-float-single")
    {
        AddArgument("attr-name", "nullable-float-single");
        AddArgument("attr-value", -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithFloat:mValue];

        [cluster writeAttributeNullableFloatSingleWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("TestCluster NullableFloatSingle write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    float mValue;
};

class SubscribeAttributeTestClusterNullableFloatSingle : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableFloatSingle()
        : SubscribeAttribute("nullable-float-single")
    {
    }

    ~SubscribeAttributeTestClusterNullableFloatSingle() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004017) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableFloatSingleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableFloatSingle response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableFloatDouble
 */
class ReadTestClusterNullableFloatDouble : public ReadAttribute {
public:
    ReadTestClusterNullableFloatDouble()
        : ReadAttribute("nullable-float-double")
    {
    }

    ~ReadTestClusterNullableFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004018) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableFloatDoubleWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableFloatDouble response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableFloatDouble read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableFloatDouble : public WriteAttribute {
public:
    WriteTestClusterNullableFloatDouble()
        : WriteAttribute("nullable-float-double")
    {
        AddArgument("attr-name", "nullable-float-double");
        AddArgument("attr-value", -std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity(), &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithDouble:mValue];

        [cluster writeAttributeNullableFloatDoubleWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("TestCluster NullableFloatDouble write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    double mValue;
};

class SubscribeAttributeTestClusterNullableFloatDouble : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableFloatDouble()
        : SubscribeAttribute("nullable-float-double")
    {
    }

    ~SubscribeAttributeTestClusterNullableFloatDouble() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004018) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableFloatDoubleWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableFloatDouble response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableOctetString
 */
class ReadTestClusterNullableOctetString : public ReadAttribute {
public:
    ReadTestClusterNullableOctetString()
        : ReadAttribute("nullable-octet-string")
    {
    }

    ~ReadTestClusterNullableOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004019) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableOctetStringWithCompletion:^(NSData * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableOctetString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableOctetString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableOctetString : public WriteAttribute {
public:
    WriteTestClusterNullableOctetString()
        : WriteAttribute("nullable-octet-string")
    {
        AddArgument("attr-name", "nullable-octet-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSData * _Nullable value = [[NSData alloc] initWithBytes:mValue.data() length:mValue.size()];

        [cluster writeAttributeNullableOctetStringWithValue:value
                                                     params:params
                                                 completion:^(NSError * _Nullable error) {
                                                     if (error != nil) {
                                                         LogNSError("TestCluster NullableOctetString write Error", error);
                                                     }
                                                     SetCommandExitStatus(error);
                                                 }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterNullableOctetString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableOctetString()
        : SubscribeAttribute("nullable-octet-string")
    {
    }

    ~SubscribeAttributeTestClusterNullableOctetString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004019) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableOctetStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSData * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableOctetString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableCharString
 */
class ReadTestClusterNullableCharString : public ReadAttribute {
public:
    ReadTestClusterNullableCharString()
        : ReadAttribute("nullable-char-string")
    {
    }

    ~ReadTestClusterNullableCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000401E) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableCharStringWithCompletion:^(NSString * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableCharString response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableCharString read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableCharString : public WriteAttribute {
public:
    WriteTestClusterNullableCharString()
        : WriteAttribute("nullable-char-string")
    {
        AddArgument("attr-name", "nullable-char-string");
        AddArgument("attr-value", &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000401E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSString * _Nullable value = [[NSString alloc] initWithBytes:mValue.data()
                                                              length:mValue.size()
                                                            encoding:NSUTF8StringEncoding];

        [cluster writeAttributeNullableCharStringWithValue:value
                                                    params:params
                                                completion:^(NSError * _Nullable error) {
                                                    if (error != nil) {
                                                        LogNSError("TestCluster NullableCharString write Error", error);
                                                    }
                                                    SetCommandExitStatus(error);
                                                }];
        return CHIP_NO_ERROR;
    }

private:
    chip::ByteSpan mValue;
};

class SubscribeAttributeTestClusterNullableCharString : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableCharString()
        : SubscribeAttribute("nullable-char-string")
    {
    }

    ~SubscribeAttributeTestClusterNullableCharString() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000401E) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableCharStringWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSString * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableCharString response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableEnumAttr
 */
class ReadTestClusterNullableEnumAttr : public ReadAttribute {
public:
    ReadTestClusterNullableEnumAttr()
        : ReadAttribute("nullable-enum-attr")
    {
    }

    ~ReadTestClusterNullableEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004024) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableEnumAttrWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableEnumAttr response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableEnumAttr read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableEnumAttr : public WriteAttribute {
public:
    WriteTestClusterNullableEnumAttr()
        : WriteAttribute("nullable-enum-attr")
    {
        AddArgument("attr-name", "nullable-enum-attr");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableEnumAttrWithValue:value
                                                  params:params
                                              completion:^(NSError * _Nullable error) {
                                                  if (error != nil) {
                                                      LogNSError("TestCluster NullableEnumAttr write Error", error);
                                                  }
                                                  SetCommandExitStatus(error);
                                              }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableEnumAttr : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableEnumAttr()
        : SubscribeAttribute("nullable-enum-attr")
    {
    }

    ~SubscribeAttributeTestClusterNullableEnumAttr() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004024) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableEnumAttrWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableEnumAttr response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableStruct
 */
class ReadTestClusterNullableStruct : public ReadAttribute {
public:
    ReadTestClusterNullableStruct()
        : ReadAttribute("nullable-struct")
    {
    }

    ~ReadTestClusterNullableStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004025) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableStructWithCompletion:^(
            MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableStruct response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableStruct read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableStruct : public WriteAttribute {
public:
    WriteTestClusterNullableStruct()
        : WriteAttribute("nullable-struct")
        , mComplex(&mValue)
    {
        AddArgument("attr-name", "nullable-struct");
        AddArgument("attr-value", &mComplex);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        MTRTestClusterClusterSimpleStruct * _Nullable value;
        if (mValue.IsNull()) {
            value = nil;
        } else {
            value = [MTRTestClusterClusterSimpleStruct new];
            value.a = [NSNumber numberWithUnsignedChar:mValue.Value().a];
            value.b = [NSNumber numberWithBool:mValue.Value().b];
            value.c = [NSNumber numberWithUnsignedChar:chip::to_underlying(mValue.Value().c)];
            value.d = [NSData dataWithBytes:mValue.Value().d.data() length:mValue.Value().d.size()];
            value.e = [[NSString alloc] initWithBytes:mValue.Value().e.data()
                                               length:mValue.Value().e.size()
                                             encoding:NSUTF8StringEncoding];
            value.f = [NSNumber numberWithUnsignedChar:mValue.Value().f.Raw()];
            value.g = [NSNumber numberWithFloat:mValue.Value().g];
            value.h = [NSNumber numberWithDouble:mValue.Value().h];
        }

        [cluster writeAttributeNullableStructWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster NullableStruct write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type> mValue;
    TypedComplexArgument<chip::app::DataModel::Nullable<chip::app::Clusters::TestCluster::Structs::SimpleStruct::Type>> mComplex;
};

class SubscribeAttributeTestClusterNullableStruct : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableStruct()
        : SubscribeAttribute("nullable-struct")
    {
    }

    ~SubscribeAttributeTestClusterNullableStruct() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004025) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableStructWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(MTRTestClusterClusterSimpleStruct * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableStruct response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt8u
 */
class ReadTestClusterNullableRangeRestrictedInt8u : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt8u()
        : ReadAttribute("nullable-range-restricted-int8u")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004026) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt8u : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt8u()
        : WriteAttribute("nullable-range-restricted-int8u")
    {
        AddArgument("attr-name", "nullable-range-restricted-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeNullableRangeRestrictedInt8uWithValue:value
                                                              params:params
                                                          completion:^(NSError * _Nullable error) {
                                                              if (error != nil) {
                                                                  LogNSError("TestCluster NullableRangeRestrictedInt8u write Error",
                                                                      error);
                                                              }
                                                              SetCommandExitStatus(error);
                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt8u()
        : SubscribeAttribute("nullable-range-restricted-int8u")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004026) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt8s
 */
class ReadTestClusterNullableRangeRestrictedInt8s : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt8s()
        : ReadAttribute("nullable-range-restricted-int8s")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004027) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt8sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt8s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt8s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt8s : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt8s()
        : WriteAttribute("nullable-range-restricted-int8s")
    {
        AddArgument("attr-name", "nullable-range-restricted-int8s");
        AddArgument("attr-value", INT8_MIN, INT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithChar:mValue];

        [cluster writeAttributeNullableRangeRestrictedInt8sWithValue:value
                                                              params:params
                                                          completion:^(NSError * _Nullable error) {
                                                              if (error != nil) {
                                                                  LogNSError("TestCluster NullableRangeRestrictedInt8s write Error",
                                                                      error);
                                                              }
                                                              SetCommandExitStatus(error);
                                                          }];
        return CHIP_NO_ERROR;
    }

private:
    int8_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt8s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt8s()
        : SubscribeAttribute("nullable-range-restricted-int8s")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt8s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004027) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt8sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt8s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt16u
 */
class ReadTestClusterNullableRangeRestrictedInt16u : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt16u()
        : ReadAttribute("nullable-range-restricted-int16u")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004028) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt16uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt16u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt16u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt16u : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt16u()
        : WriteAttribute("nullable-range-restricted-int16u")
    {
        AddArgument("attr-name", "nullable-range-restricted-int16u");
        AddArgument("attr-value", 0, UINT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithUnsignedShort:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt16uWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "TestCluster NullableRangeRestrictedInt16u write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    uint16_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt16u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt16u()
        : SubscribeAttribute("nullable-range-restricted-int16u")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt16u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004028) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt16uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt16u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute NullableRangeRestrictedInt16s
 */
class ReadTestClusterNullableRangeRestrictedInt16s : public ReadAttribute {
public:
    ReadTestClusterNullableRangeRestrictedInt16s()
        : ReadAttribute("nullable-range-restricted-int16s")
    {
    }

    ~ReadTestClusterNullableRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x00004029) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeNullableRangeRestrictedInt16sWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.NullableRangeRestrictedInt16s response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster NullableRangeRestrictedInt16s read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterNullableRangeRestrictedInt16s : public WriteAttribute {
public:
    WriteTestClusterNullableRangeRestrictedInt16s()
        : WriteAttribute("nullable-range-restricted-int16s")
    {
        AddArgument("attr-name", "nullable-range-restricted-int16s");
        AddArgument("attr-value", INT16_MIN, INT16_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterNullableRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x00004029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nullable value = [NSNumber numberWithShort:mValue];

        [cluster
            writeAttributeNullableRangeRestrictedInt16sWithValue:value
                                                          params:params
                                                      completion:^(NSError * _Nullable error) {
                                                          if (error != nil) {
                                                              LogNSError(
                                                                  "TestCluster NullableRangeRestrictedInt16s write Error", error);
                                                          }
                                                          SetCommandExitStatus(error);
                                                      }];
        return CHIP_NO_ERROR;
    }

private:
    int16_t mValue;
};

class SubscribeAttributeTestClusterNullableRangeRestrictedInt16s : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterNullableRangeRestrictedInt16s()
        : SubscribeAttribute("nullable-range-restricted-int16s")
    {
    }

    ~SubscribeAttributeTestClusterNullableRangeRestrictedInt16s() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x00004029) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeNullableRangeRestrictedInt16sWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.NullableRangeRestrictedInt16s response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute WriteOnlyInt8u
 */
class ReadTestClusterWriteOnlyInt8u : public ReadAttribute {
public:
    ReadTestClusterWriteOnlyInt8u()
        : ReadAttribute("write-only-int8u")
    {
    }

    ~ReadTestClusterWriteOnlyInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000402A) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeWriteOnlyInt8uWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.WriteOnlyInt8u response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster WriteOnlyInt8u read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class WriteTestClusterWriteOnlyInt8u : public WriteAttribute {
public:
    WriteTestClusterWriteOnlyInt8u()
        : WriteAttribute("write-only-int8u")
    {
        AddArgument("attr-name", "write-only-int8u");
        AddArgument("attr-value", 0, UINT8_MAX, &mValue);
        WriteAttribute::AddArguments();
    }

    ~WriteTestClusterWriteOnlyInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) WriteAttribute (0x0000402A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRWriteParams * params = [[MTRWriteParams alloc] init];
        params.timedWriteTimeout
            = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil;
        params.dataVersion = mDataVersion.HasValue() ? [NSNumber numberWithUnsignedInt:mDataVersion.Value()] : nil;
        NSNumber * _Nonnull value = [NSNumber numberWithUnsignedChar:mValue];

        [cluster writeAttributeWriteOnlyInt8uWithValue:value
                                                params:params
                                            completion:^(NSError * _Nullable error) {
                                                if (error != nil) {
                                                    LogNSError("TestCluster WriteOnlyInt8u write Error", error);
                                                }
                                                SetCommandExitStatus(error);
                                            }];
        return CHIP_NO_ERROR;
    }

private:
    uint8_t mValue;
};

class SubscribeAttributeTestClusterWriteOnlyInt8u : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterWriteOnlyInt8u()
        : SubscribeAttribute("write-only-int8u")
    {
    }

    ~SubscribeAttributeTestClusterWriteOnlyInt8u() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000402A) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeWriteOnlyInt8uWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.WriteOnlyInt8u response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute GeneratedCommandList
 */
class ReadTestClusterGeneratedCommandList : public ReadAttribute {
public:
    ReadTestClusterGeneratedCommandList()
        : ReadAttribute("generated-command-list")
    {
    }

    ~ReadTestClusterGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFF8) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeGeneratedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.GeneratedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster GeneratedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterGeneratedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterGeneratedCommandList()
        : SubscribeAttribute("generated-command-list")
    {
    }

    ~SubscribeAttributeTestClusterGeneratedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFF8) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeGeneratedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.GeneratedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AcceptedCommandList
 */
class ReadTestClusterAcceptedCommandList : public ReadAttribute {
public:
    ReadTestClusterAcceptedCommandList()
        : ReadAttribute("accepted-command-list")
    {
    }

    ~ReadTestClusterAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFF9) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAcceptedCommandListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.AcceptedCommandList response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster AcceptedCommandList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterAcceptedCommandList : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterAcceptedCommandList()
        : SubscribeAttribute("accepted-command-list")
    {
    }

    ~SubscribeAttributeTestClusterAcceptedCommandList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFF9) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAcceptedCommandListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.AcceptedCommandList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute AttributeList
 */
class ReadTestClusterAttributeList : public ReadAttribute {
public:
    ReadTestClusterAttributeList()
        : ReadAttribute("attribute-list")
    {
    }

    ~ReadTestClusterAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFB) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeAttributeListWithCompletion:^(NSArray * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.AttributeList response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster AttributeList read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterAttributeList : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterAttributeList()
        : SubscribeAttribute("attribute-list")
    {
    }

    ~SubscribeAttributeTestClusterAttributeList() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFB) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeAttributeListWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSArray * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.AttributeList response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute FeatureMap
 */
class ReadTestClusterFeatureMap : public ReadAttribute {
public:
    ReadTestClusterFeatureMap()
        : ReadAttribute("feature-map")
    {
    }

    ~ReadTestClusterFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFC) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeFeatureMapWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.FeatureMap response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster FeatureMap read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterFeatureMap : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterFeatureMap()
        : SubscribeAttribute("feature-map")
    {
    }

    ~SubscribeAttributeTestClusterFeatureMap() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFC) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeFeatureMapWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.FeatureMap response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*
 * Attribute ClusterRevision
 */
class ReadTestClusterClusterRevision : public ReadAttribute {
public:
    ReadTestClusterClusterRevision()
        : ReadAttribute("cluster-revision")
    {
    }

    ~ReadTestClusterClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReadAttribute (0x0000FFFD) on endpoint %u", endpointId);

        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        [cluster readAttributeClusterRevisionWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
            NSLog(@"TestCluster.ClusterRevision response %@", [value description]);
            if (error != nil) {
                LogNSError("TestCluster ClusterRevision read Error", error);
            }
            SetCommandExitStatus(error);
        }];
        return CHIP_NO_ERROR;
    }
};

class SubscribeAttributeTestClusterClusterRevision : public SubscribeAttribute {
public:
    SubscribeAttributeTestClusterClusterRevision()
        : SubscribeAttribute("cluster-revision")
    {
    }

    ~SubscribeAttributeTestClusterClusterRevision() {}

    CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
    {
        ChipLogProgress(chipTool, "Sending cluster (0xFFF1FC05) ReportAttribute (0x0000FFFD) on endpoint %u", endpointId);
        dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
        MTRBaseClusterTestCluster * cluster = [[MTRBaseClusterTestCluster alloc] initWithDevice:device
                                                                                     endpointID:@(endpointId)
                                                                                          queue:callbackQueue];
        MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
        if (mKeepSubscriptions.HasValue()) {
            params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
        }
        if (mFabricFiltered.HasValue()) {
            params.filterByFabric = mFabricFiltered.Value();
        }
        [cluster subscribeAttributeClusterRevisionWithParams:params
            subscriptionEstablished:^() {
                mSubscriptionEstablished = YES;
            }
            reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
                NSLog(@"TestCluster.ClusterRevision response %@", [value description]);
                SetCommandExitStatus(error);
            }];

        return CHIP_NO_ERROR;
    }
};

/*----------------------------------------------------------------------------*\
| Register all Clusters commands                                               |
\*----------------------------------------------------------------------------*/
void registerClusterIdentify(Commands & commands)
{
    using namespace chip::app::Clusters::Identify;

    const char * clusterName = "Identify";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<IdentifyIdentify>(), //
        make_unique<IdentifyTriggerEffect>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadIdentifyIdentifyTime>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteIdentifyIdentifyTime>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeIdentifyIdentifyTime>(), //
        make_unique<ReadIdentifyIdentifyType>(), //
        make_unique<SubscribeAttributeIdentifyIdentifyType>(), //
        make_unique<ReadIdentifyGeneratedCommandList>(), //
        make_unique<SubscribeAttributeIdentifyGeneratedCommandList>(), //
        make_unique<ReadIdentifyAcceptedCommandList>(), //
        make_unique<SubscribeAttributeIdentifyAcceptedCommandList>(), //
        make_unique<ReadIdentifyAttributeList>(), //
        make_unique<SubscribeAttributeIdentifyAttributeList>(), //
        make_unique<ReadIdentifyFeatureMap>(), //
        make_unique<SubscribeAttributeIdentifyFeatureMap>(), //
        make_unique<ReadIdentifyClusterRevision>(), //
        make_unique<SubscribeAttributeIdentifyClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGroups(Commands & commands)
{
    using namespace chip::app::Clusters::Groups;

    const char * clusterName = "Groups";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GroupsAddGroup>(), //
        make_unique<GroupsViewGroup>(), //
        make_unique<GroupsGetGroupMembership>(), //
        make_unique<GroupsRemoveGroup>(), //
        make_unique<GroupsRemoveAllGroups>(), //
        make_unique<GroupsAddGroupIfIdentifying>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGroupsNameSupport>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGroupsNameSupport>(), //
        make_unique<ReadGroupsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGroupsGeneratedCommandList>(), //
        make_unique<ReadGroupsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGroupsAcceptedCommandList>(), //
        make_unique<ReadGroupsAttributeList>(), //
        make_unique<SubscribeAttributeGroupsAttributeList>(), //
        make_unique<ReadGroupsFeatureMap>(), //
        make_unique<SubscribeAttributeGroupsFeatureMap>(), //
        make_unique<ReadGroupsClusterRevision>(), //
        make_unique<SubscribeAttributeGroupsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterScenes(Commands & commands)
{
    using namespace chip::app::Clusters::Scenes;

    const char * clusterName = "Scenes";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ScenesAddScene>(), //
        make_unique<ScenesViewScene>(), //
        make_unique<ScenesRemoveScene>(), //
        make_unique<ScenesRemoveAllScenes>(), //
        make_unique<ScenesStoreScene>(), //
        make_unique<ScenesRecallScene>(), //
        make_unique<ScenesGetSceneMembership>(), //
        make_unique<ScenesEnhancedAddScene>(), //
        make_unique<ScenesEnhancedViewScene>(), //
        make_unique<ScenesCopyScene>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadScenesSceneCount>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeScenesSceneCount>(), //
        make_unique<ReadScenesCurrentScene>(), //
        make_unique<SubscribeAttributeScenesCurrentScene>(), //
        make_unique<ReadScenesCurrentGroup>(), //
        make_unique<SubscribeAttributeScenesCurrentGroup>(), //
        make_unique<ReadScenesSceneValid>(), //
        make_unique<SubscribeAttributeScenesSceneValid>(), //
        make_unique<ReadScenesNameSupport>(), //
        make_unique<SubscribeAttributeScenesNameSupport>(), //
        make_unique<ReadScenesLastConfiguredBy>(), //
        make_unique<SubscribeAttributeScenesLastConfiguredBy>(), //
        make_unique<ReadScenesGeneratedCommandList>(), //
        make_unique<SubscribeAttributeScenesGeneratedCommandList>(), //
        make_unique<ReadScenesAcceptedCommandList>(), //
        make_unique<SubscribeAttributeScenesAcceptedCommandList>(), //
        make_unique<ReadScenesAttributeList>(), //
        make_unique<SubscribeAttributeScenesAttributeList>(), //
        make_unique<ReadScenesFeatureMap>(), //
        make_unique<SubscribeAttributeScenesFeatureMap>(), //
        make_unique<ReadScenesClusterRevision>(), //
        make_unique<SubscribeAttributeScenesClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOnOff(Commands & commands)
{
    using namespace chip::app::Clusters::OnOff;

    const char * clusterName = "OnOff";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OnOffOff>(), //
        make_unique<OnOffOn>(), //
        make_unique<OnOffToggle>(), //
        make_unique<OnOffOffWithEffect>(), //
        make_unique<OnOffOnWithRecallGlobalScene>(), //
        make_unique<OnOffOnWithTimedOff>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOnOffOnOff>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOnOffOnOff>(), //
        make_unique<ReadOnOffGlobalSceneControl>(), //
        make_unique<SubscribeAttributeOnOffGlobalSceneControl>(), //
        make_unique<ReadOnOffOnTime>(), //
        make_unique<WriteOnOffOnTime>(), //
        make_unique<SubscribeAttributeOnOffOnTime>(), //
        make_unique<ReadOnOffOffWaitTime>(), //
        make_unique<WriteOnOffOffWaitTime>(), //
        make_unique<SubscribeAttributeOnOffOffWaitTime>(), //
        make_unique<ReadOnOffStartUpOnOff>(), //
        make_unique<WriteOnOffStartUpOnOff>(), //
        make_unique<SubscribeAttributeOnOffStartUpOnOff>(), //
        make_unique<ReadOnOffGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOnOffGeneratedCommandList>(), //
        make_unique<ReadOnOffAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOnOffAcceptedCommandList>(), //
        make_unique<ReadOnOffAttributeList>(), //
        make_unique<SubscribeAttributeOnOffAttributeList>(), //
        make_unique<ReadOnOffFeatureMap>(), //
        make_unique<SubscribeAttributeOnOffFeatureMap>(), //
        make_unique<ReadOnOffClusterRevision>(), //
        make_unique<SubscribeAttributeOnOffClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOnOffSwitchConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::OnOffSwitchConfiguration;

    const char * clusterName = "OnOffSwitchConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOnOffSwitchConfigurationSwitchType>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationSwitchType>(), //
        make_unique<ReadOnOffSwitchConfigurationSwitchActions>(), //
        make_unique<WriteOnOffSwitchConfigurationSwitchActions>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationSwitchActions>(), //
        make_unique<ReadOnOffSwitchConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationGeneratedCommandList>(), //
        make_unique<ReadOnOffSwitchConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationAcceptedCommandList>(), //
        make_unique<ReadOnOffSwitchConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationAttributeList>(), //
        make_unique<ReadOnOffSwitchConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationFeatureMap>(), //
        make_unique<ReadOnOffSwitchConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeOnOffSwitchConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterLevelControl(Commands & commands)
{
    using namespace chip::app::Clusters::LevelControl;

    const char * clusterName = "LevelControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<LevelControlMoveToLevel>(), //
        make_unique<LevelControlMove>(), //
        make_unique<LevelControlStep>(), //
        make_unique<LevelControlStop>(), //
        make_unique<LevelControlMoveToLevelWithOnOff>(), //
        make_unique<LevelControlMoveWithOnOff>(), //
        make_unique<LevelControlStepWithOnOff>(), //
        make_unique<LevelControlStopWithOnOff>(), //
        make_unique<LevelControlMoveToClosestFrequency>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadLevelControlCurrentLevel>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeLevelControlCurrentLevel>(), //
        make_unique<ReadLevelControlRemainingTime>(), //
        make_unique<SubscribeAttributeLevelControlRemainingTime>(), //
        make_unique<ReadLevelControlMinLevel>(), //
        make_unique<SubscribeAttributeLevelControlMinLevel>(), //
        make_unique<ReadLevelControlMaxLevel>(), //
        make_unique<SubscribeAttributeLevelControlMaxLevel>(), //
        make_unique<ReadLevelControlCurrentFrequency>(), //
        make_unique<SubscribeAttributeLevelControlCurrentFrequency>(), //
        make_unique<ReadLevelControlMinFrequency>(), //
        make_unique<SubscribeAttributeLevelControlMinFrequency>(), //
        make_unique<ReadLevelControlMaxFrequency>(), //
        make_unique<SubscribeAttributeLevelControlMaxFrequency>(), //
        make_unique<ReadLevelControlOptions>(), //
        make_unique<WriteLevelControlOptions>(), //
        make_unique<SubscribeAttributeLevelControlOptions>(), //
        make_unique<ReadLevelControlOnOffTransitionTime>(), //
        make_unique<WriteLevelControlOnOffTransitionTime>(), //
        make_unique<SubscribeAttributeLevelControlOnOffTransitionTime>(), //
        make_unique<ReadLevelControlOnLevel>(), //
        make_unique<WriteLevelControlOnLevel>(), //
        make_unique<SubscribeAttributeLevelControlOnLevel>(), //
        make_unique<ReadLevelControlOnTransitionTime>(), //
        make_unique<WriteLevelControlOnTransitionTime>(), //
        make_unique<SubscribeAttributeLevelControlOnTransitionTime>(), //
        make_unique<ReadLevelControlOffTransitionTime>(), //
        make_unique<WriteLevelControlOffTransitionTime>(), //
        make_unique<SubscribeAttributeLevelControlOffTransitionTime>(), //
        make_unique<ReadLevelControlDefaultMoveRate>(), //
        make_unique<WriteLevelControlDefaultMoveRate>(), //
        make_unique<SubscribeAttributeLevelControlDefaultMoveRate>(), //
        make_unique<ReadLevelControlStartUpCurrentLevel>(), //
        make_unique<WriteLevelControlStartUpCurrentLevel>(), //
        make_unique<SubscribeAttributeLevelControlStartUpCurrentLevel>(), //
        make_unique<ReadLevelControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeLevelControlGeneratedCommandList>(), //
        make_unique<ReadLevelControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeLevelControlAcceptedCommandList>(), //
        make_unique<ReadLevelControlAttributeList>(), //
        make_unique<SubscribeAttributeLevelControlAttributeList>(), //
        make_unique<ReadLevelControlFeatureMap>(), //
        make_unique<SubscribeAttributeLevelControlFeatureMap>(), //
        make_unique<ReadLevelControlClusterRevision>(), //
        make_unique<SubscribeAttributeLevelControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBinaryInputBasic(Commands & commands)
{
    using namespace chip::app::Clusters::BinaryInputBasic;

    const char * clusterName = "BinaryInputBasic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBinaryInputBasicActiveText>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteBinaryInputBasicActiveText>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBinaryInputBasicActiveText>(), //
        make_unique<ReadBinaryInputBasicDescription>(), //
        make_unique<WriteBinaryInputBasicDescription>(), //
        make_unique<SubscribeAttributeBinaryInputBasicDescription>(), //
        make_unique<ReadBinaryInputBasicInactiveText>(), //
        make_unique<WriteBinaryInputBasicInactiveText>(), //
        make_unique<SubscribeAttributeBinaryInputBasicInactiveText>(), //
        make_unique<ReadBinaryInputBasicOutOfService>(), //
        make_unique<WriteBinaryInputBasicOutOfService>(), //
        make_unique<SubscribeAttributeBinaryInputBasicOutOfService>(), //
        make_unique<ReadBinaryInputBasicPolarity>(), //
        make_unique<SubscribeAttributeBinaryInputBasicPolarity>(), //
        make_unique<ReadBinaryInputBasicPresentValue>(), //
        make_unique<WriteBinaryInputBasicPresentValue>(), //
        make_unique<SubscribeAttributeBinaryInputBasicPresentValue>(), //
        make_unique<ReadBinaryInputBasicReliability>(), //
        make_unique<WriteBinaryInputBasicReliability>(), //
        make_unique<SubscribeAttributeBinaryInputBasicReliability>(), //
        make_unique<ReadBinaryInputBasicStatusFlags>(), //
        make_unique<SubscribeAttributeBinaryInputBasicStatusFlags>(), //
        make_unique<ReadBinaryInputBasicApplicationType>(), //
        make_unique<SubscribeAttributeBinaryInputBasicApplicationType>(), //
        make_unique<ReadBinaryInputBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicGeneratedCommandList>(), //
        make_unique<ReadBinaryInputBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicAcceptedCommandList>(), //
        make_unique<ReadBinaryInputBasicAttributeList>(), //
        make_unique<SubscribeAttributeBinaryInputBasicAttributeList>(), //
        make_unique<ReadBinaryInputBasicFeatureMap>(), //
        make_unique<SubscribeAttributeBinaryInputBasicFeatureMap>(), //
        make_unique<ReadBinaryInputBasicClusterRevision>(), //
        make_unique<SubscribeAttributeBinaryInputBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterDescriptor(Commands & commands)
{
    using namespace chip::app::Clusters::Descriptor;

    const char * clusterName = "Descriptor";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadDescriptorDeviceTypeList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeDescriptorDeviceTypeList>(), //
        make_unique<ReadDescriptorServerList>(), //
        make_unique<SubscribeAttributeDescriptorServerList>(), //
        make_unique<ReadDescriptorClientList>(), //
        make_unique<SubscribeAttributeDescriptorClientList>(), //
        make_unique<ReadDescriptorPartsList>(), //
        make_unique<SubscribeAttributeDescriptorPartsList>(), //
        make_unique<ReadDescriptorGeneratedCommandList>(), //
        make_unique<SubscribeAttributeDescriptorGeneratedCommandList>(), //
        make_unique<ReadDescriptorAcceptedCommandList>(), //
        make_unique<SubscribeAttributeDescriptorAcceptedCommandList>(), //
        make_unique<ReadDescriptorAttributeList>(), //
        make_unique<SubscribeAttributeDescriptorAttributeList>(), //
        make_unique<ReadDescriptorFeatureMap>(), //
        make_unique<SubscribeAttributeDescriptorFeatureMap>(), //
        make_unique<ReadDescriptorClusterRevision>(), //
        make_unique<SubscribeAttributeDescriptorClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBinding(Commands & commands)
{
    using namespace chip::app::Clusters::Binding;

    const char * clusterName = "Binding";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBindingBinding>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteBindingBinding>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBindingBinding>(), //
        make_unique<ReadBindingGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBindingGeneratedCommandList>(), //
        make_unique<ReadBindingAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBindingAcceptedCommandList>(), //
        make_unique<ReadBindingAttributeList>(), //
        make_unique<SubscribeAttributeBindingAttributeList>(), //
        make_unique<ReadBindingFeatureMap>(), //
        make_unique<SubscribeAttributeBindingFeatureMap>(), //
        make_unique<ReadBindingClusterRevision>(), //
        make_unique<SubscribeAttributeBindingClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAccessControl(Commands & commands)
{
    using namespace chip::app::Clusters::AccessControl;

    const char * clusterName = "AccessControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAccessControlAcl>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteAccessControlAcl>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAccessControlAcl>(), //
        make_unique<ReadAccessControlExtension>(), //
        make_unique<WriteAccessControlExtension>(), //
        make_unique<SubscribeAttributeAccessControlExtension>(), //
        make_unique<ReadAccessControlSubjectsPerAccessControlEntry>(), //
        make_unique<SubscribeAttributeAccessControlSubjectsPerAccessControlEntry>(), //
        make_unique<ReadAccessControlTargetsPerAccessControlEntry>(), //
        make_unique<SubscribeAttributeAccessControlTargetsPerAccessControlEntry>(), //
        make_unique<ReadAccessControlAccessControlEntriesPerFabric>(), //
        make_unique<SubscribeAttributeAccessControlAccessControlEntriesPerFabric>(), //
        make_unique<ReadAccessControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAccessControlGeneratedCommandList>(), //
        make_unique<ReadAccessControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAccessControlAcceptedCommandList>(), //
        make_unique<ReadAccessControlAttributeList>(), //
        make_unique<SubscribeAttributeAccessControlAttributeList>(), //
        make_unique<ReadAccessControlFeatureMap>(), //
        make_unique<SubscribeAttributeAccessControlFeatureMap>(), //
        make_unique<ReadAccessControlClusterRevision>(), //
        make_unique<SubscribeAttributeAccessControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterActions(Commands & commands)
{
    using namespace chip::app::Clusters::Actions;

    const char * clusterName = "Actions";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ActionsInstantAction>(), //
        make_unique<ActionsInstantActionWithTransition>(), //
        make_unique<ActionsStartAction>(), //
        make_unique<ActionsStartActionWithDuration>(), //
        make_unique<ActionsStopAction>(), //
        make_unique<ActionsPauseAction>(), //
        make_unique<ActionsPauseActionWithDuration>(), //
        make_unique<ActionsResumeAction>(), //
        make_unique<ActionsEnableAction>(), //
        make_unique<ActionsEnableActionWithDuration>(), //
        make_unique<ActionsDisableAction>(), //
        make_unique<ActionsDisableActionWithDuration>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadActionsActionList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeActionsActionList>(), //
        make_unique<ReadActionsEndpointLists>(), //
        make_unique<SubscribeAttributeActionsEndpointLists>(), //
        make_unique<ReadActionsSetupURL>(), //
        make_unique<SubscribeAttributeActionsSetupURL>(), //
        make_unique<ReadActionsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeActionsGeneratedCommandList>(), //
        make_unique<ReadActionsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeActionsAcceptedCommandList>(), //
        make_unique<ReadActionsAttributeList>(), //
        make_unique<SubscribeAttributeActionsAttributeList>(), //
        make_unique<ReadActionsFeatureMap>(), //
        make_unique<SubscribeAttributeActionsFeatureMap>(), //
        make_unique<ReadActionsClusterRevision>(), //
        make_unique<SubscribeAttributeActionsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBasic(Commands & commands)
{
    using namespace chip::app::Clusters::Basic;

    const char * clusterName = "Basic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<BasicMfgSpecificPing>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBasicDataModelRevision>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBasicDataModelRevision>(), //
        make_unique<ReadBasicVendorName>(), //
        make_unique<SubscribeAttributeBasicVendorName>(), //
        make_unique<ReadBasicVendorID>(), //
        make_unique<SubscribeAttributeBasicVendorID>(), //
        make_unique<ReadBasicProductName>(), //
        make_unique<SubscribeAttributeBasicProductName>(), //
        make_unique<ReadBasicProductID>(), //
        make_unique<SubscribeAttributeBasicProductID>(), //
        make_unique<ReadBasicNodeLabel>(), //
        make_unique<WriteBasicNodeLabel>(), //
        make_unique<SubscribeAttributeBasicNodeLabel>(), //
        make_unique<ReadBasicLocation>(), //
        make_unique<WriteBasicLocation>(), //
        make_unique<SubscribeAttributeBasicLocation>(), //
        make_unique<ReadBasicHardwareVersion>(), //
        make_unique<SubscribeAttributeBasicHardwareVersion>(), //
        make_unique<ReadBasicHardwareVersionString>(), //
        make_unique<SubscribeAttributeBasicHardwareVersionString>(), //
        make_unique<ReadBasicSoftwareVersion>(), //
        make_unique<SubscribeAttributeBasicSoftwareVersion>(), //
        make_unique<ReadBasicSoftwareVersionString>(), //
        make_unique<SubscribeAttributeBasicSoftwareVersionString>(), //
        make_unique<ReadBasicManufacturingDate>(), //
        make_unique<SubscribeAttributeBasicManufacturingDate>(), //
        make_unique<ReadBasicPartNumber>(), //
        make_unique<SubscribeAttributeBasicPartNumber>(), //
        make_unique<ReadBasicProductURL>(), //
        make_unique<SubscribeAttributeBasicProductURL>(), //
        make_unique<ReadBasicProductLabel>(), //
        make_unique<SubscribeAttributeBasicProductLabel>(), //
        make_unique<ReadBasicSerialNumber>(), //
        make_unique<SubscribeAttributeBasicSerialNumber>(), //
        make_unique<ReadBasicLocalConfigDisabled>(), //
        make_unique<WriteBasicLocalConfigDisabled>(), //
        make_unique<SubscribeAttributeBasicLocalConfigDisabled>(), //
        make_unique<ReadBasicReachable>(), //
        make_unique<SubscribeAttributeBasicReachable>(), //
        make_unique<ReadBasicUniqueID>(), //
        make_unique<SubscribeAttributeBasicUniqueID>(), //
        make_unique<ReadBasicCapabilityMinima>(), //
        make_unique<SubscribeAttributeBasicCapabilityMinima>(), //
        make_unique<ReadBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBasicGeneratedCommandList>(), //
        make_unique<ReadBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBasicAcceptedCommandList>(), //
        make_unique<ReadBasicAttributeList>(), //
        make_unique<SubscribeAttributeBasicAttributeList>(), //
        make_unique<ReadBasicFeatureMap>(), //
        make_unique<SubscribeAttributeBasicFeatureMap>(), //
        make_unique<ReadBasicClusterRevision>(), //
        make_unique<SubscribeAttributeBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOtaSoftwareUpdateProvider(Commands & commands)
{
    using namespace chip::app::Clusters::OtaSoftwareUpdateProvider;

    const char * clusterName = "OtaSoftwareUpdateProvider";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OtaSoftwareUpdateProviderQueryImage>(), //
        make_unique<OtaSoftwareUpdateProviderApplyUpdateRequest>(), //
        make_unique<OtaSoftwareUpdateProviderNotifyUpdateApplied>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOtaSoftwareUpdateProviderGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderGeneratedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateProviderAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderAcceptedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateProviderAttributeList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderAttributeList>(), //
        make_unique<ReadOtaSoftwareUpdateProviderFeatureMap>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderFeatureMap>(), //
        make_unique<ReadOtaSoftwareUpdateProviderClusterRevision>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateProviderClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOtaSoftwareUpdateRequestor(Commands & commands)
{
    using namespace chip::app::Clusters::OtaSoftwareUpdateRequestor;

    const char * clusterName = "OtaSoftwareUpdateRequestor";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OtaSoftwareUpdateRequestorAnnounceOtaProvider>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOtaSoftwareUpdateRequestorDefaultOtaProviders>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteOtaSoftwareUpdateRequestorDefaultOtaProviders>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorDefaultOtaProviders>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorUpdatePossible>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorUpdatePossible>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorUpdateState>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorUpdateState>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorUpdateStateProgress>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorUpdateStateProgress>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorGeneratedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorAcceptedCommandList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorAttributeList>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorAttributeList>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorFeatureMap>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorFeatureMap>(), //
        make_unique<ReadOtaSoftwareUpdateRequestorClusterRevision>(), //
        make_unique<SubscribeAttributeOtaSoftwareUpdateRequestorClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterLocalizationConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::LocalizationConfiguration;

    const char * clusterName = "LocalizationConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadLocalizationConfigurationActiveLocale>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteLocalizationConfigurationActiveLocale>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeLocalizationConfigurationActiveLocale>(), //
        make_unique<ReadLocalizationConfigurationSupportedLocales>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationSupportedLocales>(), //
        make_unique<ReadLocalizationConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationGeneratedCommandList>(), //
        make_unique<ReadLocalizationConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationAcceptedCommandList>(), //
        make_unique<ReadLocalizationConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationAttributeList>(), //
        make_unique<ReadLocalizationConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationFeatureMap>(), //
        make_unique<ReadLocalizationConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeLocalizationConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTimeFormatLocalization(Commands & commands)
{
    using namespace chip::app::Clusters::TimeFormatLocalization;

    const char * clusterName = "TimeFormatLocalization";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTimeFormatLocalizationHourFormat>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteTimeFormatLocalizationHourFormat>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTimeFormatLocalizationHourFormat>(), //
        make_unique<ReadTimeFormatLocalizationActiveCalendarType>(), //
        make_unique<WriteTimeFormatLocalizationActiveCalendarType>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationActiveCalendarType>(), //
        make_unique<ReadTimeFormatLocalizationSupportedCalendarTypes>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationSupportedCalendarTypes>(), //
        make_unique<ReadTimeFormatLocalizationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationGeneratedCommandList>(), //
        make_unique<ReadTimeFormatLocalizationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationAcceptedCommandList>(), //
        make_unique<ReadTimeFormatLocalizationAttributeList>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationAttributeList>(), //
        make_unique<ReadTimeFormatLocalizationFeatureMap>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationFeatureMap>(), //
        make_unique<ReadTimeFormatLocalizationClusterRevision>(), //
        make_unique<SubscribeAttributeTimeFormatLocalizationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterUnitLocalization(Commands & commands)
{
    using namespace chip::app::Clusters::UnitLocalization;

    const char * clusterName = "UnitLocalization";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadUnitLocalizationTemperatureUnit>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteUnitLocalizationTemperatureUnit>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeUnitLocalizationTemperatureUnit>(), //
        make_unique<ReadUnitLocalizationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeUnitLocalizationGeneratedCommandList>(), //
        make_unique<ReadUnitLocalizationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeUnitLocalizationAcceptedCommandList>(), //
        make_unique<ReadUnitLocalizationAttributeList>(), //
        make_unique<SubscribeAttributeUnitLocalizationAttributeList>(), //
        make_unique<ReadUnitLocalizationFeatureMap>(), //
        make_unique<SubscribeAttributeUnitLocalizationFeatureMap>(), //
        make_unique<ReadUnitLocalizationClusterRevision>(), //
        make_unique<SubscribeAttributeUnitLocalizationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPowerSourceConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::PowerSourceConfiguration;

    const char * clusterName = "PowerSourceConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPowerSourceConfigurationSources>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePowerSourceConfigurationSources>(), //
        make_unique<ReadPowerSourceConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationGeneratedCommandList>(), //
        make_unique<ReadPowerSourceConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationAcceptedCommandList>(), //
        make_unique<ReadPowerSourceConfigurationAttributeList>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationAttributeList>(), //
        make_unique<ReadPowerSourceConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationFeatureMap>(), //
        make_unique<ReadPowerSourceConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributePowerSourceConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPowerSource(Commands & commands)
{
    using namespace chip::app::Clusters::PowerSource;

    const char * clusterName = "PowerSource";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPowerSourceStatus>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePowerSourceStatus>(), //
        make_unique<ReadPowerSourceOrder>(), //
        make_unique<SubscribeAttributePowerSourceOrder>(), //
        make_unique<ReadPowerSourceDescription>(), //
        make_unique<SubscribeAttributePowerSourceDescription>(), //
        make_unique<ReadPowerSourceWiredAssessedInputVoltage>(), //
        make_unique<SubscribeAttributePowerSourceWiredAssessedInputVoltage>(), //
        make_unique<ReadPowerSourceWiredAssessedInputFrequency>(), //
        make_unique<SubscribeAttributePowerSourceWiredAssessedInputFrequency>(), //
        make_unique<ReadPowerSourceWiredCurrentType>(), //
        make_unique<SubscribeAttributePowerSourceWiredCurrentType>(), //
        make_unique<ReadPowerSourceWiredAssessedCurrent>(), //
        make_unique<SubscribeAttributePowerSourceWiredAssessedCurrent>(), //
        make_unique<ReadPowerSourceWiredNominalVoltage>(), //
        make_unique<SubscribeAttributePowerSourceWiredNominalVoltage>(), //
        make_unique<ReadPowerSourceWiredMaximumCurrent>(), //
        make_unique<SubscribeAttributePowerSourceWiredMaximumCurrent>(), //
        make_unique<ReadPowerSourceWiredPresent>(), //
        make_unique<SubscribeAttributePowerSourceWiredPresent>(), //
        make_unique<ReadPowerSourceActiveWiredFaults>(), //
        make_unique<SubscribeAttributePowerSourceActiveWiredFaults>(), //
        make_unique<ReadPowerSourceBatVoltage>(), //
        make_unique<SubscribeAttributePowerSourceBatVoltage>(), //
        make_unique<ReadPowerSourceBatPercentRemaining>(), //
        make_unique<SubscribeAttributePowerSourceBatPercentRemaining>(), //
        make_unique<ReadPowerSourceBatTimeRemaining>(), //
        make_unique<SubscribeAttributePowerSourceBatTimeRemaining>(), //
        make_unique<ReadPowerSourceBatChargeLevel>(), //
        make_unique<SubscribeAttributePowerSourceBatChargeLevel>(), //
        make_unique<ReadPowerSourceBatReplacementNeeded>(), //
        make_unique<SubscribeAttributePowerSourceBatReplacementNeeded>(), //
        make_unique<ReadPowerSourceBatReplaceability>(), //
        make_unique<SubscribeAttributePowerSourceBatReplaceability>(), //
        make_unique<ReadPowerSourceBatPresent>(), //
        make_unique<SubscribeAttributePowerSourceBatPresent>(), //
        make_unique<ReadPowerSourceActiveBatFaults>(), //
        make_unique<SubscribeAttributePowerSourceActiveBatFaults>(), //
        make_unique<ReadPowerSourceBatReplacementDescription>(), //
        make_unique<SubscribeAttributePowerSourceBatReplacementDescription>(), //
        make_unique<ReadPowerSourceBatCommonDesignation>(), //
        make_unique<SubscribeAttributePowerSourceBatCommonDesignation>(), //
        make_unique<ReadPowerSourceBatANSIDesignation>(), //
        make_unique<SubscribeAttributePowerSourceBatANSIDesignation>(), //
        make_unique<ReadPowerSourceBatIECDesignation>(), //
        make_unique<SubscribeAttributePowerSourceBatIECDesignation>(), //
        make_unique<ReadPowerSourceBatApprovedChemistry>(), //
        make_unique<SubscribeAttributePowerSourceBatApprovedChemistry>(), //
        make_unique<ReadPowerSourceBatCapacity>(), //
        make_unique<SubscribeAttributePowerSourceBatCapacity>(), //
        make_unique<ReadPowerSourceBatQuantity>(), //
        make_unique<SubscribeAttributePowerSourceBatQuantity>(), //
        make_unique<ReadPowerSourceBatChargeState>(), //
        make_unique<SubscribeAttributePowerSourceBatChargeState>(), //
        make_unique<ReadPowerSourceBatTimeToFullCharge>(), //
        make_unique<SubscribeAttributePowerSourceBatTimeToFullCharge>(), //
        make_unique<ReadPowerSourceBatFunctionalWhileCharging>(), //
        make_unique<SubscribeAttributePowerSourceBatFunctionalWhileCharging>(), //
        make_unique<ReadPowerSourceBatChargingCurrent>(), //
        make_unique<SubscribeAttributePowerSourceBatChargingCurrent>(), //
        make_unique<ReadPowerSourceActiveBatChargeFaults>(), //
        make_unique<SubscribeAttributePowerSourceActiveBatChargeFaults>(), //
        make_unique<ReadPowerSourceGeneratedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceGeneratedCommandList>(), //
        make_unique<ReadPowerSourceAcceptedCommandList>(), //
        make_unique<SubscribeAttributePowerSourceAcceptedCommandList>(), //
        make_unique<ReadPowerSourceAttributeList>(), //
        make_unique<SubscribeAttributePowerSourceAttributeList>(), //
        make_unique<ReadPowerSourceFeatureMap>(), //
        make_unique<SubscribeAttributePowerSourceFeatureMap>(), //
        make_unique<ReadPowerSourceClusterRevision>(), //
        make_unique<SubscribeAttributePowerSourceClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGeneralCommissioning(Commands & commands)
{
    using namespace chip::app::Clusters::GeneralCommissioning;

    const char * clusterName = "GeneralCommissioning";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GeneralCommissioningArmFailSafe>(), //
        make_unique<GeneralCommissioningSetRegulatoryConfig>(), //
        make_unique<GeneralCommissioningCommissioningComplete>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGeneralCommissioningBreadcrumb>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteGeneralCommissioningBreadcrumb>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGeneralCommissioningBreadcrumb>(), //
        make_unique<ReadGeneralCommissioningBasicCommissioningInfo>(), //
        make_unique<SubscribeAttributeGeneralCommissioningBasicCommissioningInfo>(), //
        make_unique<ReadGeneralCommissioningRegulatoryConfig>(), //
        make_unique<SubscribeAttributeGeneralCommissioningRegulatoryConfig>(), //
        make_unique<ReadGeneralCommissioningLocationCapability>(), //
        make_unique<SubscribeAttributeGeneralCommissioningLocationCapability>(), //
        make_unique<ReadGeneralCommissioningSupportsConcurrentConnection>(), //
        make_unique<SubscribeAttributeGeneralCommissioningSupportsConcurrentConnection>(), //
        make_unique<ReadGeneralCommissioningGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningGeneratedCommandList>(), //
        make_unique<ReadGeneralCommissioningAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningAcceptedCommandList>(), //
        make_unique<ReadGeneralCommissioningAttributeList>(), //
        make_unique<SubscribeAttributeGeneralCommissioningAttributeList>(), //
        make_unique<ReadGeneralCommissioningFeatureMap>(), //
        make_unique<SubscribeAttributeGeneralCommissioningFeatureMap>(), //
        make_unique<ReadGeneralCommissioningClusterRevision>(), //
        make_unique<SubscribeAttributeGeneralCommissioningClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterNetworkCommissioning(Commands & commands)
{
    using namespace chip::app::Clusters::NetworkCommissioning;

    const char * clusterName = "NetworkCommissioning";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<NetworkCommissioningScanNetworks>(), //
        make_unique<NetworkCommissioningAddOrUpdateWiFiNetwork>(), //
        make_unique<NetworkCommissioningAddOrUpdateThreadNetwork>(), //
        make_unique<NetworkCommissioningRemoveNetwork>(), //
        make_unique<NetworkCommissioningConnectNetwork>(), //
        make_unique<NetworkCommissioningReorderNetwork>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadNetworkCommissioningMaxNetworks>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeNetworkCommissioningMaxNetworks>(), //
        make_unique<ReadNetworkCommissioningNetworks>(), //
        make_unique<SubscribeAttributeNetworkCommissioningNetworks>(), //
        make_unique<ReadNetworkCommissioningScanMaxTimeSeconds>(), //
        make_unique<SubscribeAttributeNetworkCommissioningScanMaxTimeSeconds>(), //
        make_unique<ReadNetworkCommissioningConnectMaxTimeSeconds>(), //
        make_unique<SubscribeAttributeNetworkCommissioningConnectMaxTimeSeconds>(), //
        make_unique<ReadNetworkCommissioningInterfaceEnabled>(), //
        make_unique<WriteNetworkCommissioningInterfaceEnabled>(), //
        make_unique<SubscribeAttributeNetworkCommissioningInterfaceEnabled>(), //
        make_unique<ReadNetworkCommissioningLastNetworkingStatus>(), //
        make_unique<SubscribeAttributeNetworkCommissioningLastNetworkingStatus>(), //
        make_unique<ReadNetworkCommissioningLastNetworkID>(), //
        make_unique<SubscribeAttributeNetworkCommissioningLastNetworkID>(), //
        make_unique<ReadNetworkCommissioningLastConnectErrorValue>(), //
        make_unique<SubscribeAttributeNetworkCommissioningLastConnectErrorValue>(), //
        make_unique<ReadNetworkCommissioningGeneratedCommandList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningGeneratedCommandList>(), //
        make_unique<ReadNetworkCommissioningAcceptedCommandList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningAcceptedCommandList>(), //
        make_unique<ReadNetworkCommissioningAttributeList>(), //
        make_unique<SubscribeAttributeNetworkCommissioningAttributeList>(), //
        make_unique<ReadNetworkCommissioningFeatureMap>(), //
        make_unique<SubscribeAttributeNetworkCommissioningFeatureMap>(), //
        make_unique<ReadNetworkCommissioningClusterRevision>(), //
        make_unique<SubscribeAttributeNetworkCommissioningClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterDiagnosticLogs(Commands & commands)
{
    using namespace chip::app::Clusters::DiagnosticLogs;

    const char * clusterName = "DiagnosticLogs";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<DiagnosticLogsRetrieveLogsRequest>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadDiagnosticLogsGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeDiagnosticLogsGeneratedCommandList>(), //
        make_unique<ReadDiagnosticLogsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeDiagnosticLogsAcceptedCommandList>(), //
        make_unique<ReadDiagnosticLogsAttributeList>(), //
        make_unique<SubscribeAttributeDiagnosticLogsAttributeList>(), //
        make_unique<ReadDiagnosticLogsFeatureMap>(), //
        make_unique<SubscribeAttributeDiagnosticLogsFeatureMap>(), //
        make_unique<ReadDiagnosticLogsClusterRevision>(), //
        make_unique<SubscribeAttributeDiagnosticLogsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGeneralDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::GeneralDiagnostics;

    const char * clusterName = "GeneralDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GeneralDiagnosticsTestEventTrigger>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGeneralDiagnosticsNetworkInterfaces>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGeneralDiagnosticsNetworkInterfaces>(), //
        make_unique<ReadGeneralDiagnosticsRebootCount>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsRebootCount>(), //
        make_unique<ReadGeneralDiagnosticsUpTime>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsUpTime>(), //
        make_unique<ReadGeneralDiagnosticsTotalOperationalHours>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsTotalOperationalHours>(), //
        make_unique<ReadGeneralDiagnosticsBootReasons>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsBootReasons>(), //
        make_unique<ReadGeneralDiagnosticsActiveHardwareFaults>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsActiveHardwareFaults>(), //
        make_unique<ReadGeneralDiagnosticsActiveRadioFaults>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsActiveRadioFaults>(), //
        make_unique<ReadGeneralDiagnosticsActiveNetworkFaults>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsActiveNetworkFaults>(), //
        make_unique<ReadGeneralDiagnosticsTestEventTriggersEnabled>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsTestEventTriggersEnabled>(), //
        make_unique<ReadGeneralDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadGeneralDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadGeneralDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsAttributeList>(), //
        make_unique<ReadGeneralDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsFeatureMap>(), //
        make_unique<ReadGeneralDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeGeneralDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterSoftwareDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::SoftwareDiagnostics;

    const char * clusterName = "SoftwareDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<SoftwareDiagnosticsResetWatermarks>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadSoftwareDiagnosticsThreadMetrics>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsThreadMetrics>(), //
        make_unique<ReadSoftwareDiagnosticsCurrentHeapFree>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsCurrentHeapFree>(), //
        make_unique<ReadSoftwareDiagnosticsCurrentHeapUsed>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsCurrentHeapUsed>(), //
        make_unique<ReadSoftwareDiagnosticsCurrentHeapHighWatermark>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsCurrentHeapHighWatermark>(), //
        make_unique<ReadSoftwareDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadSoftwareDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadSoftwareDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsAttributeList>(), //
        make_unique<ReadSoftwareDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsFeatureMap>(), //
        make_unique<ReadSoftwareDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeSoftwareDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterThreadNetworkDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::ThreadNetworkDiagnostics;

    const char * clusterName = "ThreadNetworkDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ThreadNetworkDiagnosticsResetCounts>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadThreadNetworkDiagnosticsChannel>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsChannel>(), //
        make_unique<ReadThreadNetworkDiagnosticsRoutingRole>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRoutingRole>(), //
        make_unique<ReadThreadNetworkDiagnosticsNetworkName>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsNetworkName>(), //
        make_unique<ReadThreadNetworkDiagnosticsPanId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPanId>(), //
        make_unique<ReadThreadNetworkDiagnosticsExtendedPanId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsExtendedPanId>(), //
        make_unique<ReadThreadNetworkDiagnosticsMeshLocalPrefix>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsMeshLocalPrefix>(), //
        make_unique<ReadThreadNetworkDiagnosticsOverrunCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsOverrunCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsNeighborTableList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsNeighborTableList>(), //
        make_unique<ReadThreadNetworkDiagnosticsRouteTableList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRouteTableList>(), //
        make_unique<ReadThreadNetworkDiagnosticsPartitionId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPartitionId>(), //
        make_unique<ReadThreadNetworkDiagnosticsWeighting>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsWeighting>(), //
        make_unique<ReadThreadNetworkDiagnosticsDataVersion>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsDataVersion>(), //
        make_unique<ReadThreadNetworkDiagnosticsStableDataVersion>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsStableDataVersion>(), //
        make_unique<ReadThreadNetworkDiagnosticsLeaderRouterId>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsLeaderRouterId>(), //
        make_unique<ReadThreadNetworkDiagnosticsDetachedRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsDetachedRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsChildRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsChildRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRouterRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRouterRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsLeaderRoleCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsLeaderRoleCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsAttachAttemptCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAttachAttemptCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsPartitionIdChangeCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPartitionIdChangeCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsBetterPartitionAttachAttemptCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsParentChangeCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsParentChangeCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxTotalCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxTotalCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxUnicastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxUnicastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxBroadcastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxBroadcastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxAckRequestedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxAckRequestedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxAckedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxAckedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxNoAckRequestedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxNoAckRequestedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxDataCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxDataCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxDataPollCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxDataPollCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxBeaconCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxBeaconCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxBeaconRequestCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxBeaconRequestCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxOtherCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxOtherCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxRetryCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxRetryCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxDirectMaxRetryExpiryCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxIndirectMaxRetryExpiryCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxErrCcaCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxErrCcaCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxErrAbortCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxErrAbortCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsTxErrBusyChannelCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsTxErrBusyChannelCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxTotalCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxTotalCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxUnicastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxUnicastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxBroadcastCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxBroadcastCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDataCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDataCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDataPollCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDataPollCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxBeaconCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxBeaconCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxBeaconRequestCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxBeaconRequestCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxOtherCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxOtherCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxAddressFilteredCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxAddressFilteredCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDestAddrFilteredCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDestAddrFilteredCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxDuplicatedCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxDuplicatedCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrNoFrameCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrNoFrameCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrUnknownNeighborCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrUnknownNeighborCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrInvalidSrcAddrCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrSecCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrSecCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrFcsCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrFcsCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsRxErrOtherCount>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsRxErrOtherCount>(), //
        make_unique<ReadThreadNetworkDiagnosticsActiveTimestamp>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsActiveTimestamp>(), //
        make_unique<ReadThreadNetworkDiagnosticsPendingTimestamp>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsPendingTimestamp>(), //
        make_unique<ReadThreadNetworkDiagnosticsDelay>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsDelay>(), //
        make_unique<ReadThreadNetworkDiagnosticsSecurityPolicy>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsSecurityPolicy>(), //
        make_unique<ReadThreadNetworkDiagnosticsChannelPage0Mask>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsChannelPage0Mask>(), //
        make_unique<ReadThreadNetworkDiagnosticsOperationalDatasetComponents>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsOperationalDatasetComponents>(), //
        make_unique<ReadThreadNetworkDiagnosticsActiveNetworkFaultsList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsActiveNetworkFaultsList>(), //
        make_unique<ReadThreadNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadThreadNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadThreadNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadThreadNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadThreadNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeThreadNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWiFiNetworkDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::WiFiNetworkDiagnostics;

    const char * clusterName = "WiFiNetworkDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<WiFiNetworkDiagnosticsResetCounts>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWiFiNetworkDiagnosticsBssid>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsBssid>(), //
        make_unique<ReadWiFiNetworkDiagnosticsSecurityType>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsSecurityType>(), //
        make_unique<ReadWiFiNetworkDiagnosticsWiFiVersion>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsWiFiVersion>(), //
        make_unique<ReadWiFiNetworkDiagnosticsChannelNumber>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsChannelNumber>(), //
        make_unique<ReadWiFiNetworkDiagnosticsRssi>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsRssi>(), //
        make_unique<ReadWiFiNetworkDiagnosticsBeaconLostCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsBeaconLostCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsBeaconRxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsBeaconRxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketMulticastRxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastRxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketMulticastTxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketMulticastTxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketUnicastRxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastRxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsPacketUnicastTxCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsPacketUnicastTxCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsCurrentMaxRate>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsCurrentMaxRate>(), //
        make_unique<ReadWiFiNetworkDiagnosticsOverrunCount>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsOverrunCount>(), //
        make_unique<ReadWiFiNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadWiFiNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadWiFiNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeWiFiNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterEthernetNetworkDiagnostics(Commands & commands)
{
    using namespace chip::app::Clusters::EthernetNetworkDiagnostics;

    const char * clusterName = "EthernetNetworkDiagnostics";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<EthernetNetworkDiagnosticsResetCounts>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadEthernetNetworkDiagnosticsPHYRate>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsPHYRate>(), //
        make_unique<ReadEthernetNetworkDiagnosticsFullDuplex>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsFullDuplex>(), //
        make_unique<ReadEthernetNetworkDiagnosticsPacketRxCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsPacketRxCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsPacketTxCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsPacketTxCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsTxErrCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsTxErrCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsCollisionCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsCollisionCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsOverrunCount>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsOverrunCount>(), //
        make_unique<ReadEthernetNetworkDiagnosticsCarrierDetect>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsCarrierDetect>(), //
        make_unique<ReadEthernetNetworkDiagnosticsTimeSinceReset>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsTimeSinceReset>(), //
        make_unique<ReadEthernetNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsGeneratedCommandList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsAcceptedCommandList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsAttributeList>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsAttributeList>(), //
        make_unique<ReadEthernetNetworkDiagnosticsFeatureMap>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsFeatureMap>(), //
        make_unique<ReadEthernetNetworkDiagnosticsClusterRevision>(), //
        make_unique<SubscribeAttributeEthernetNetworkDiagnosticsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBridgedDeviceBasic(Commands & commands)
{
    using namespace chip::app::Clusters::BridgedDeviceBasic;

    const char * clusterName = "BridgedDeviceBasic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBridgedDeviceBasicVendorName>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBridgedDeviceBasicVendorName>(), //
        make_unique<ReadBridgedDeviceBasicVendorID>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicVendorID>(), //
        make_unique<ReadBridgedDeviceBasicProductName>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicProductName>(), //
        make_unique<ReadBridgedDeviceBasicNodeLabel>(), //
        make_unique<WriteBridgedDeviceBasicNodeLabel>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicNodeLabel>(), //
        make_unique<ReadBridgedDeviceBasicHardwareVersion>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicHardwareVersion>(), //
        make_unique<ReadBridgedDeviceBasicHardwareVersionString>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicHardwareVersionString>(), //
        make_unique<ReadBridgedDeviceBasicSoftwareVersion>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicSoftwareVersion>(), //
        make_unique<ReadBridgedDeviceBasicSoftwareVersionString>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicSoftwareVersionString>(), //
        make_unique<ReadBridgedDeviceBasicManufacturingDate>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicManufacturingDate>(), //
        make_unique<ReadBridgedDeviceBasicPartNumber>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicPartNumber>(), //
        make_unique<ReadBridgedDeviceBasicProductURL>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicProductURL>(), //
        make_unique<ReadBridgedDeviceBasicProductLabel>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicProductLabel>(), //
        make_unique<ReadBridgedDeviceBasicSerialNumber>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicSerialNumber>(), //
        make_unique<ReadBridgedDeviceBasicReachable>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicReachable>(), //
        make_unique<ReadBridgedDeviceBasicUniqueID>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicUniqueID>(), //
        make_unique<ReadBridgedDeviceBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicGeneratedCommandList>(), //
        make_unique<ReadBridgedDeviceBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicAcceptedCommandList>(), //
        make_unique<ReadBridgedDeviceBasicAttributeList>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicAttributeList>(), //
        make_unique<ReadBridgedDeviceBasicFeatureMap>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicFeatureMap>(), //
        make_unique<ReadBridgedDeviceBasicClusterRevision>(), //
        make_unique<SubscribeAttributeBridgedDeviceBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterSwitch(Commands & commands)
{
    using namespace chip::app::Clusters::Switch;

    const char * clusterName = "Switch";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadSwitchNumberOfPositions>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeSwitchNumberOfPositions>(), //
        make_unique<ReadSwitchCurrentPosition>(), //
        make_unique<SubscribeAttributeSwitchCurrentPosition>(), //
        make_unique<ReadSwitchMultiPressMax>(), //
        make_unique<SubscribeAttributeSwitchMultiPressMax>(), //
        make_unique<ReadSwitchGeneratedCommandList>(), //
        make_unique<SubscribeAttributeSwitchGeneratedCommandList>(), //
        make_unique<ReadSwitchAcceptedCommandList>(), //
        make_unique<SubscribeAttributeSwitchAcceptedCommandList>(), //
        make_unique<ReadSwitchAttributeList>(), //
        make_unique<SubscribeAttributeSwitchAttributeList>(), //
        make_unique<ReadSwitchFeatureMap>(), //
        make_unique<SubscribeAttributeSwitchFeatureMap>(), //
        make_unique<ReadSwitchClusterRevision>(), //
        make_unique<SubscribeAttributeSwitchClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAdministratorCommissioning(Commands & commands)
{
    using namespace chip::app::Clusters::AdministratorCommissioning;

    const char * clusterName = "AdministratorCommissioning";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<AdministratorCommissioningOpenCommissioningWindow>(), //
        make_unique<AdministratorCommissioningOpenBasicCommissioningWindow>(), //
        make_unique<AdministratorCommissioningRevokeCommissioning>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAdministratorCommissioningWindowStatus>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAdministratorCommissioningWindowStatus>(), //
        make_unique<ReadAdministratorCommissioningAdminFabricIndex>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAdminFabricIndex>(), //
        make_unique<ReadAdministratorCommissioningAdminVendorId>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAdminVendorId>(), //
        make_unique<ReadAdministratorCommissioningGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningGeneratedCommandList>(), //
        make_unique<ReadAdministratorCommissioningAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAcceptedCommandList>(), //
        make_unique<ReadAdministratorCommissioningAttributeList>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningAttributeList>(), //
        make_unique<ReadAdministratorCommissioningFeatureMap>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningFeatureMap>(), //
        make_unique<ReadAdministratorCommissioningClusterRevision>(), //
        make_unique<SubscribeAttributeAdministratorCommissioningClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOperationalCredentials(Commands & commands)
{
    using namespace chip::app::Clusters::OperationalCredentials;

    const char * clusterName = "OperationalCredentials";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<OperationalCredentialsAttestationRequest>(), //
        make_unique<OperationalCredentialsCertificateChainRequest>(), //
        make_unique<OperationalCredentialsCSRRequest>(), //
        make_unique<OperationalCredentialsAddNOC>(), //
        make_unique<OperationalCredentialsUpdateNOC>(), //
        make_unique<OperationalCredentialsUpdateFabricLabel>(), //
        make_unique<OperationalCredentialsRemoveFabric>(), //
        make_unique<OperationalCredentialsAddTrustedRootCertificate>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOperationalCredentialsNOCs>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOperationalCredentialsNOCs>(), //
        make_unique<ReadOperationalCredentialsFabrics>(), //
        make_unique<SubscribeAttributeOperationalCredentialsFabrics>(), //
        make_unique<ReadOperationalCredentialsSupportedFabrics>(), //
        make_unique<SubscribeAttributeOperationalCredentialsSupportedFabrics>(), //
        make_unique<ReadOperationalCredentialsCommissionedFabrics>(), //
        make_unique<SubscribeAttributeOperationalCredentialsCommissionedFabrics>(), //
        make_unique<ReadOperationalCredentialsTrustedRootCertificates>(), //
        make_unique<SubscribeAttributeOperationalCredentialsTrustedRootCertificates>(), //
        make_unique<ReadOperationalCredentialsCurrentFabricIndex>(), //
        make_unique<SubscribeAttributeOperationalCredentialsCurrentFabricIndex>(), //
        make_unique<ReadOperationalCredentialsGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsGeneratedCommandList>(), //
        make_unique<ReadOperationalCredentialsAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsAcceptedCommandList>(), //
        make_unique<ReadOperationalCredentialsAttributeList>(), //
        make_unique<SubscribeAttributeOperationalCredentialsAttributeList>(), //
        make_unique<ReadOperationalCredentialsFeatureMap>(), //
        make_unique<SubscribeAttributeOperationalCredentialsFeatureMap>(), //
        make_unique<ReadOperationalCredentialsClusterRevision>(), //
        make_unique<SubscribeAttributeOperationalCredentialsClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterGroupKeyManagement(Commands & commands)
{
    using namespace chip::app::Clusters::GroupKeyManagement;

    const char * clusterName = "GroupKeyManagement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<GroupKeyManagementKeySetWrite>(), //
        make_unique<GroupKeyManagementKeySetRead>(), //
        make_unique<GroupKeyManagementKeySetRemove>(), //
        make_unique<GroupKeyManagementKeySetReadAllIndices>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadGroupKeyManagementGroupKeyMap>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteGroupKeyManagementGroupKeyMap>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeGroupKeyManagementGroupKeyMap>(), //
        make_unique<ReadGroupKeyManagementGroupTable>(), //
        make_unique<SubscribeAttributeGroupKeyManagementGroupTable>(), //
        make_unique<ReadGroupKeyManagementMaxGroupsPerFabric>(), //
        make_unique<SubscribeAttributeGroupKeyManagementMaxGroupsPerFabric>(), //
        make_unique<ReadGroupKeyManagementMaxGroupKeysPerFabric>(), //
        make_unique<SubscribeAttributeGroupKeyManagementMaxGroupKeysPerFabric>(), //
        make_unique<ReadGroupKeyManagementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementGeneratedCommandList>(), //
        make_unique<ReadGroupKeyManagementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementAcceptedCommandList>(), //
        make_unique<ReadGroupKeyManagementAttributeList>(), //
        make_unique<SubscribeAttributeGroupKeyManagementAttributeList>(), //
        make_unique<ReadGroupKeyManagementFeatureMap>(), //
        make_unique<SubscribeAttributeGroupKeyManagementFeatureMap>(), //
        make_unique<ReadGroupKeyManagementClusterRevision>(), //
        make_unique<SubscribeAttributeGroupKeyManagementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFixedLabel(Commands & commands)
{
    using namespace chip::app::Clusters::FixedLabel;

    const char * clusterName = "FixedLabel";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFixedLabelLabelList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFixedLabelLabelList>(), //
        make_unique<ReadFixedLabelGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFixedLabelGeneratedCommandList>(), //
        make_unique<ReadFixedLabelAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFixedLabelAcceptedCommandList>(), //
        make_unique<ReadFixedLabelAttributeList>(), //
        make_unique<SubscribeAttributeFixedLabelAttributeList>(), //
        make_unique<ReadFixedLabelFeatureMap>(), //
        make_unique<SubscribeAttributeFixedLabelFeatureMap>(), //
        make_unique<ReadFixedLabelClusterRevision>(), //
        make_unique<SubscribeAttributeFixedLabelClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterUserLabel(Commands & commands)
{
    using namespace chip::app::Clusters::UserLabel;

    const char * clusterName = "UserLabel";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadUserLabelLabelList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteUserLabelLabelList>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeUserLabelLabelList>(), //
        make_unique<ReadUserLabelGeneratedCommandList>(), //
        make_unique<SubscribeAttributeUserLabelGeneratedCommandList>(), //
        make_unique<ReadUserLabelAcceptedCommandList>(), //
        make_unique<SubscribeAttributeUserLabelAcceptedCommandList>(), //
        make_unique<ReadUserLabelAttributeList>(), //
        make_unique<SubscribeAttributeUserLabelAttributeList>(), //
        make_unique<ReadUserLabelFeatureMap>(), //
        make_unique<SubscribeAttributeUserLabelFeatureMap>(), //
        make_unique<ReadUserLabelClusterRevision>(), //
        make_unique<SubscribeAttributeUserLabelClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBooleanState(Commands & commands)
{
    using namespace chip::app::Clusters::BooleanState;

    const char * clusterName = "BooleanState";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBooleanStateStateValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBooleanStateStateValue>(), //
        make_unique<ReadBooleanStateGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBooleanStateGeneratedCommandList>(), //
        make_unique<ReadBooleanStateAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBooleanStateAcceptedCommandList>(), //
        make_unique<ReadBooleanStateAttributeList>(), //
        make_unique<SubscribeAttributeBooleanStateAttributeList>(), //
        make_unique<ReadBooleanStateFeatureMap>(), //
        make_unique<SubscribeAttributeBooleanStateFeatureMap>(), //
        make_unique<ReadBooleanStateClusterRevision>(), //
        make_unique<SubscribeAttributeBooleanStateClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterModeSelect(Commands & commands)
{
    using namespace chip::app::Clusters::ModeSelect;

    const char * clusterName = "ModeSelect";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ModeSelectChangeToMode>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadModeSelectDescription>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeModeSelectDescription>(), //
        make_unique<ReadModeSelectStandardNamespace>(), //
        make_unique<SubscribeAttributeModeSelectStandardNamespace>(), //
        make_unique<ReadModeSelectSupportedModes>(), //
        make_unique<SubscribeAttributeModeSelectSupportedModes>(), //
        make_unique<ReadModeSelectCurrentMode>(), //
        make_unique<SubscribeAttributeModeSelectCurrentMode>(), //
        make_unique<ReadModeSelectStartUpMode>(), //
        make_unique<WriteModeSelectStartUpMode>(), //
        make_unique<SubscribeAttributeModeSelectStartUpMode>(), //
        make_unique<ReadModeSelectOnMode>(), //
        make_unique<WriteModeSelectOnMode>(), //
        make_unique<SubscribeAttributeModeSelectOnMode>(), //
        make_unique<ReadModeSelectGeneratedCommandList>(), //
        make_unique<SubscribeAttributeModeSelectGeneratedCommandList>(), //
        make_unique<ReadModeSelectAcceptedCommandList>(), //
        make_unique<SubscribeAttributeModeSelectAcceptedCommandList>(), //
        make_unique<ReadModeSelectAttributeList>(), //
        make_unique<SubscribeAttributeModeSelectAttributeList>(), //
        make_unique<ReadModeSelectFeatureMap>(), //
        make_unique<SubscribeAttributeModeSelectFeatureMap>(), //
        make_unique<ReadModeSelectClusterRevision>(), //
        make_unique<SubscribeAttributeModeSelectClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterDoorLock(Commands & commands)
{
    using namespace chip::app::Clusters::DoorLock;

    const char * clusterName = "DoorLock";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<DoorLockLockDoor>(), //
        make_unique<DoorLockUnlockDoor>(), //
        make_unique<DoorLockUnlockWithTimeout>(), //
        make_unique<DoorLockSetWeekDaySchedule>(), //
        make_unique<DoorLockGetWeekDaySchedule>(), //
        make_unique<DoorLockClearWeekDaySchedule>(), //
        make_unique<DoorLockSetYearDaySchedule>(), //
        make_unique<DoorLockGetYearDaySchedule>(), //
        make_unique<DoorLockClearYearDaySchedule>(), //
        make_unique<DoorLockSetHolidaySchedule>(), //
        make_unique<DoorLockGetHolidaySchedule>(), //
        make_unique<DoorLockClearHolidaySchedule>(), //
        make_unique<DoorLockSetUser>(), //
        make_unique<DoorLockGetUser>(), //
        make_unique<DoorLockClearUser>(), //
        make_unique<DoorLockSetCredential>(), //
        make_unique<DoorLockGetCredentialStatus>(), //
        make_unique<DoorLockClearCredential>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadDoorLockLockState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeDoorLockLockState>(), //
        make_unique<ReadDoorLockLockType>(), //
        make_unique<SubscribeAttributeDoorLockLockType>(), //
        make_unique<ReadDoorLockActuatorEnabled>(), //
        make_unique<SubscribeAttributeDoorLockActuatorEnabled>(), //
        make_unique<ReadDoorLockDoorState>(), //
        make_unique<SubscribeAttributeDoorLockDoorState>(), //
        make_unique<ReadDoorLockDoorOpenEvents>(), //
        make_unique<WriteDoorLockDoorOpenEvents>(), //
        make_unique<SubscribeAttributeDoorLockDoorOpenEvents>(), //
        make_unique<ReadDoorLockDoorClosedEvents>(), //
        make_unique<WriteDoorLockDoorClosedEvents>(), //
        make_unique<SubscribeAttributeDoorLockDoorClosedEvents>(), //
        make_unique<ReadDoorLockOpenPeriod>(), //
        make_unique<WriteDoorLockOpenPeriod>(), //
        make_unique<SubscribeAttributeDoorLockOpenPeriod>(), //
        make_unique<ReadDoorLockNumberOfTotalUsersSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfTotalUsersSupported>(), //
        make_unique<ReadDoorLockNumberOfPINUsersSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfPINUsersSupported>(), //
        make_unique<ReadDoorLockNumberOfRFIDUsersSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfRFIDUsersSupported>(), //
        make_unique<ReadDoorLockNumberOfWeekDaySchedulesSupportedPerUser>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfWeekDaySchedulesSupportedPerUser>(), //
        make_unique<ReadDoorLockNumberOfYearDaySchedulesSupportedPerUser>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfYearDaySchedulesSupportedPerUser>(), //
        make_unique<ReadDoorLockNumberOfHolidaySchedulesSupported>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfHolidaySchedulesSupported>(), //
        make_unique<ReadDoorLockMaxPINCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMaxPINCodeLength>(), //
        make_unique<ReadDoorLockMinPINCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMinPINCodeLength>(), //
        make_unique<ReadDoorLockMaxRFIDCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMaxRFIDCodeLength>(), //
        make_unique<ReadDoorLockMinRFIDCodeLength>(), //
        make_unique<SubscribeAttributeDoorLockMinRFIDCodeLength>(), //
        make_unique<ReadDoorLockCredentialRulesSupport>(), //
        make_unique<SubscribeAttributeDoorLockCredentialRulesSupport>(), //
        make_unique<ReadDoorLockNumberOfCredentialsSupportedPerUser>(), //
        make_unique<SubscribeAttributeDoorLockNumberOfCredentialsSupportedPerUser>(), //
        make_unique<ReadDoorLockLanguage>(), //
        make_unique<WriteDoorLockLanguage>(), //
        make_unique<SubscribeAttributeDoorLockLanguage>(), //
        make_unique<ReadDoorLockLEDSettings>(), //
        make_unique<WriteDoorLockLEDSettings>(), //
        make_unique<SubscribeAttributeDoorLockLEDSettings>(), //
        make_unique<ReadDoorLockAutoRelockTime>(), //
        make_unique<WriteDoorLockAutoRelockTime>(), //
        make_unique<SubscribeAttributeDoorLockAutoRelockTime>(), //
        make_unique<ReadDoorLockSoundVolume>(), //
        make_unique<WriteDoorLockSoundVolume>(), //
        make_unique<SubscribeAttributeDoorLockSoundVolume>(), //
        make_unique<ReadDoorLockOperatingMode>(), //
        make_unique<WriteDoorLockOperatingMode>(), //
        make_unique<SubscribeAttributeDoorLockOperatingMode>(), //
        make_unique<ReadDoorLockSupportedOperatingModes>(), //
        make_unique<SubscribeAttributeDoorLockSupportedOperatingModes>(), //
        make_unique<ReadDoorLockDefaultConfigurationRegister>(), //
        make_unique<SubscribeAttributeDoorLockDefaultConfigurationRegister>(), //
        make_unique<ReadDoorLockEnableLocalProgramming>(), //
        make_unique<WriteDoorLockEnableLocalProgramming>(), //
        make_unique<SubscribeAttributeDoorLockEnableLocalProgramming>(), //
        make_unique<ReadDoorLockEnableOneTouchLocking>(), //
        make_unique<WriteDoorLockEnableOneTouchLocking>(), //
        make_unique<SubscribeAttributeDoorLockEnableOneTouchLocking>(), //
        make_unique<ReadDoorLockEnableInsideStatusLED>(), //
        make_unique<WriteDoorLockEnableInsideStatusLED>(), //
        make_unique<SubscribeAttributeDoorLockEnableInsideStatusLED>(), //
        make_unique<ReadDoorLockEnablePrivacyModeButton>(), //
        make_unique<WriteDoorLockEnablePrivacyModeButton>(), //
        make_unique<SubscribeAttributeDoorLockEnablePrivacyModeButton>(), //
        make_unique<ReadDoorLockLocalProgrammingFeatures>(), //
        make_unique<WriteDoorLockLocalProgrammingFeatures>(), //
        make_unique<SubscribeAttributeDoorLockLocalProgrammingFeatures>(), //
        make_unique<ReadDoorLockWrongCodeEntryLimit>(), //
        make_unique<WriteDoorLockWrongCodeEntryLimit>(), //
        make_unique<SubscribeAttributeDoorLockWrongCodeEntryLimit>(), //
        make_unique<ReadDoorLockUserCodeTemporaryDisableTime>(), //
        make_unique<WriteDoorLockUserCodeTemporaryDisableTime>(), //
        make_unique<SubscribeAttributeDoorLockUserCodeTemporaryDisableTime>(), //
        make_unique<ReadDoorLockSendPINOverTheAir>(), //
        make_unique<WriteDoorLockSendPINOverTheAir>(), //
        make_unique<SubscribeAttributeDoorLockSendPINOverTheAir>(), //
        make_unique<ReadDoorLockRequirePINforRemoteOperation>(), //
        make_unique<WriteDoorLockRequirePINforRemoteOperation>(), //
        make_unique<SubscribeAttributeDoorLockRequirePINforRemoteOperation>(), //
        make_unique<ReadDoorLockExpiringUserTimeout>(), //
        make_unique<WriteDoorLockExpiringUserTimeout>(), //
        make_unique<SubscribeAttributeDoorLockExpiringUserTimeout>(), //
        make_unique<ReadDoorLockGeneratedCommandList>(), //
        make_unique<SubscribeAttributeDoorLockGeneratedCommandList>(), //
        make_unique<ReadDoorLockAcceptedCommandList>(), //
        make_unique<SubscribeAttributeDoorLockAcceptedCommandList>(), //
        make_unique<ReadDoorLockAttributeList>(), //
        make_unique<SubscribeAttributeDoorLockAttributeList>(), //
        make_unique<ReadDoorLockFeatureMap>(), //
        make_unique<SubscribeAttributeDoorLockFeatureMap>(), //
        make_unique<ReadDoorLockClusterRevision>(), //
        make_unique<SubscribeAttributeDoorLockClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWindowCovering(Commands & commands)
{
    using namespace chip::app::Clusters::WindowCovering;

    const char * clusterName = "WindowCovering";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<WindowCoveringUpOrOpen>(), //
        make_unique<WindowCoveringDownOrClose>(), //
        make_unique<WindowCoveringStopMotion>(), //
        make_unique<WindowCoveringGoToLiftValue>(), //
        make_unique<WindowCoveringGoToLiftPercentage>(), //
        make_unique<WindowCoveringGoToTiltValue>(), //
        make_unique<WindowCoveringGoToTiltPercentage>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWindowCoveringType>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWindowCoveringType>(), //
        make_unique<ReadWindowCoveringPhysicalClosedLimitLift>(), //
        make_unique<SubscribeAttributeWindowCoveringPhysicalClosedLimitLift>(), //
        make_unique<ReadWindowCoveringPhysicalClosedLimitTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringPhysicalClosedLimitTilt>(), //
        make_unique<ReadWindowCoveringCurrentPositionLift>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionLift>(), //
        make_unique<ReadWindowCoveringCurrentPositionTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionTilt>(), //
        make_unique<ReadWindowCoveringNumberOfActuationsLift>(), //
        make_unique<SubscribeAttributeWindowCoveringNumberOfActuationsLift>(), //
        make_unique<ReadWindowCoveringNumberOfActuationsTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringNumberOfActuationsTilt>(), //
        make_unique<ReadWindowCoveringConfigStatus>(), //
        make_unique<SubscribeAttributeWindowCoveringConfigStatus>(), //
        make_unique<ReadWindowCoveringCurrentPositionLiftPercentage>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionLiftPercentage>(), //
        make_unique<ReadWindowCoveringCurrentPositionTiltPercentage>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionTiltPercentage>(), //
        make_unique<ReadWindowCoveringOperationalStatus>(), //
        make_unique<SubscribeAttributeWindowCoveringOperationalStatus>(), //
        make_unique<ReadWindowCoveringTargetPositionLiftPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringTargetPositionLiftPercent100ths>(), //
        make_unique<ReadWindowCoveringTargetPositionTiltPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringTargetPositionTiltPercent100ths>(), //
        make_unique<ReadWindowCoveringEndProductType>(), //
        make_unique<SubscribeAttributeWindowCoveringEndProductType>(), //
        make_unique<ReadWindowCoveringCurrentPositionLiftPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionLiftPercent100ths>(), //
        make_unique<ReadWindowCoveringCurrentPositionTiltPercent100ths>(), //
        make_unique<SubscribeAttributeWindowCoveringCurrentPositionTiltPercent100ths>(), //
        make_unique<ReadWindowCoveringInstalledOpenLimitLift>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledOpenLimitLift>(), //
        make_unique<ReadWindowCoveringInstalledClosedLimitLift>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledClosedLimitLift>(), //
        make_unique<ReadWindowCoveringInstalledOpenLimitTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledOpenLimitTilt>(), //
        make_unique<ReadWindowCoveringInstalledClosedLimitTilt>(), //
        make_unique<SubscribeAttributeWindowCoveringInstalledClosedLimitTilt>(), //
        make_unique<ReadWindowCoveringMode>(), //
        make_unique<WriteWindowCoveringMode>(), //
        make_unique<SubscribeAttributeWindowCoveringMode>(), //
        make_unique<ReadWindowCoveringSafetyStatus>(), //
        make_unique<SubscribeAttributeWindowCoveringSafetyStatus>(), //
        make_unique<ReadWindowCoveringGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWindowCoveringGeneratedCommandList>(), //
        make_unique<ReadWindowCoveringAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWindowCoveringAcceptedCommandList>(), //
        make_unique<ReadWindowCoveringAttributeList>(), //
        make_unique<SubscribeAttributeWindowCoveringAttributeList>(), //
        make_unique<ReadWindowCoveringFeatureMap>(), //
        make_unique<SubscribeAttributeWindowCoveringFeatureMap>(), //
        make_unique<ReadWindowCoveringClusterRevision>(), //
        make_unique<SubscribeAttributeWindowCoveringClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBarrierControl(Commands & commands)
{
    using namespace chip::app::Clusters::BarrierControl;

    const char * clusterName = "BarrierControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<BarrierControlBarrierControlGoToPercent>(), //
        make_unique<BarrierControlBarrierControlStop>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBarrierControlBarrierMovingState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBarrierControlBarrierMovingState>(), //
        make_unique<ReadBarrierControlBarrierSafetyStatus>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierSafetyStatus>(), //
        make_unique<ReadBarrierControlBarrierCapabilities>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCapabilities>(), //
        make_unique<ReadBarrierControlBarrierOpenEvents>(), //
        make_unique<WriteBarrierControlBarrierOpenEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierOpenEvents>(), //
        make_unique<ReadBarrierControlBarrierCloseEvents>(), //
        make_unique<WriteBarrierControlBarrierCloseEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCloseEvents>(), //
        make_unique<ReadBarrierControlBarrierCommandOpenEvents>(), //
        make_unique<WriteBarrierControlBarrierCommandOpenEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCommandOpenEvents>(), //
        make_unique<ReadBarrierControlBarrierCommandCloseEvents>(), //
        make_unique<WriteBarrierControlBarrierCommandCloseEvents>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierCommandCloseEvents>(), //
        make_unique<ReadBarrierControlBarrierOpenPeriod>(), //
        make_unique<WriteBarrierControlBarrierOpenPeriod>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierOpenPeriod>(), //
        make_unique<ReadBarrierControlBarrierClosePeriod>(), //
        make_unique<WriteBarrierControlBarrierClosePeriod>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierClosePeriod>(), //
        make_unique<ReadBarrierControlBarrierPosition>(), //
        make_unique<SubscribeAttributeBarrierControlBarrierPosition>(), //
        make_unique<ReadBarrierControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBarrierControlGeneratedCommandList>(), //
        make_unique<ReadBarrierControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBarrierControlAcceptedCommandList>(), //
        make_unique<ReadBarrierControlAttributeList>(), //
        make_unique<SubscribeAttributeBarrierControlAttributeList>(), //
        make_unique<ReadBarrierControlFeatureMap>(), //
        make_unique<SubscribeAttributeBarrierControlFeatureMap>(), //
        make_unique<ReadBarrierControlClusterRevision>(), //
        make_unique<SubscribeAttributeBarrierControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPumpConfigurationAndControl(Commands & commands)
{
    using namespace chip::app::Clusters::PumpConfigurationAndControl;

    const char * clusterName = "PumpConfigurationAndControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPumpConfigurationAndControlMaxPressure>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMaxSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlMaxFlow>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxFlow>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMinCompPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinCompPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMaxCompPressure>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxCompPressure>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstFlow>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstFlow>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstFlow>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstFlow>(), //
        make_unique<ReadPumpConfigurationAndControlMinConstTemp>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMinConstTemp>(), //
        make_unique<ReadPumpConfigurationAndControlMaxConstTemp>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlMaxConstTemp>(), //
        make_unique<ReadPumpConfigurationAndControlPumpStatus>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlPumpStatus>(), //
        make_unique<ReadPumpConfigurationAndControlEffectiveOperationMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlEffectiveOperationMode>(), //
        make_unique<ReadPumpConfigurationAndControlEffectiveControlMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlEffectiveControlMode>(), //
        make_unique<ReadPumpConfigurationAndControlCapacity>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlCapacity>(), //
        make_unique<ReadPumpConfigurationAndControlSpeed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlSpeed>(), //
        make_unique<ReadPumpConfigurationAndControlLifetimeRunningHours>(), //
        make_unique<WritePumpConfigurationAndControlLifetimeRunningHours>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlLifetimeRunningHours>(), //
        make_unique<ReadPumpConfigurationAndControlPower>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlPower>(), //
        make_unique<ReadPumpConfigurationAndControlLifetimeEnergyConsumed>(), //
        make_unique<WritePumpConfigurationAndControlLifetimeEnergyConsumed>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlLifetimeEnergyConsumed>(), //
        make_unique<ReadPumpConfigurationAndControlOperationMode>(), //
        make_unique<WritePumpConfigurationAndControlOperationMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlOperationMode>(), //
        make_unique<ReadPumpConfigurationAndControlControlMode>(), //
        make_unique<WritePumpConfigurationAndControlControlMode>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlControlMode>(), //
        make_unique<ReadPumpConfigurationAndControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlGeneratedCommandList>(), //
        make_unique<ReadPumpConfigurationAndControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlAcceptedCommandList>(), //
        make_unique<ReadPumpConfigurationAndControlAttributeList>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlAttributeList>(), //
        make_unique<ReadPumpConfigurationAndControlFeatureMap>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlFeatureMap>(), //
        make_unique<ReadPumpConfigurationAndControlClusterRevision>(), //
        make_unique<SubscribeAttributePumpConfigurationAndControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterThermostat(Commands & commands)
{
    using namespace chip::app::Clusters::Thermostat;

    const char * clusterName = "Thermostat";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ThermostatSetpointRaiseLower>(), //
        make_unique<ThermostatSetWeeklySchedule>(), //
        make_unique<ThermostatGetWeeklySchedule>(), //
        make_unique<ThermostatClearWeeklySchedule>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadThermostatLocalTemperature>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeThermostatLocalTemperature>(), //
        make_unique<ReadThermostatOutdoorTemperature>(), //
        make_unique<SubscribeAttributeThermostatOutdoorTemperature>(), //
        make_unique<ReadThermostatOccupancy>(), //
        make_unique<SubscribeAttributeThermostatOccupancy>(), //
        make_unique<ReadThermostatAbsMinHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMinHeatSetpointLimit>(), //
        make_unique<ReadThermostatAbsMaxHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMaxHeatSetpointLimit>(), //
        make_unique<ReadThermostatAbsMinCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMinCoolSetpointLimit>(), //
        make_unique<ReadThermostatAbsMaxCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatAbsMaxCoolSetpointLimit>(), //
        make_unique<ReadThermostatPICoolingDemand>(), //
        make_unique<SubscribeAttributeThermostatPICoolingDemand>(), //
        make_unique<ReadThermostatPIHeatingDemand>(), //
        make_unique<SubscribeAttributeThermostatPIHeatingDemand>(), //
        make_unique<ReadThermostatHVACSystemTypeConfiguration>(), //
        make_unique<WriteThermostatHVACSystemTypeConfiguration>(), //
        make_unique<SubscribeAttributeThermostatHVACSystemTypeConfiguration>(), //
        make_unique<ReadThermostatLocalTemperatureCalibration>(), //
        make_unique<WriteThermostatLocalTemperatureCalibration>(), //
        make_unique<SubscribeAttributeThermostatLocalTemperatureCalibration>(), //
        make_unique<ReadThermostatOccupiedCoolingSetpoint>(), //
        make_unique<WriteThermostatOccupiedCoolingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatOccupiedCoolingSetpoint>(), //
        make_unique<ReadThermostatOccupiedHeatingSetpoint>(), //
        make_unique<WriteThermostatOccupiedHeatingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatOccupiedHeatingSetpoint>(), //
        make_unique<ReadThermostatUnoccupiedCoolingSetpoint>(), //
        make_unique<WriteThermostatUnoccupiedCoolingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedCoolingSetpoint>(), //
        make_unique<ReadThermostatUnoccupiedHeatingSetpoint>(), //
        make_unique<WriteThermostatUnoccupiedHeatingSetpoint>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedHeatingSetpoint>(), //
        make_unique<ReadThermostatMinHeatSetpointLimit>(), //
        make_unique<WriteThermostatMinHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMinHeatSetpointLimit>(), //
        make_unique<ReadThermostatMaxHeatSetpointLimit>(), //
        make_unique<WriteThermostatMaxHeatSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMaxHeatSetpointLimit>(), //
        make_unique<ReadThermostatMinCoolSetpointLimit>(), //
        make_unique<WriteThermostatMinCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMinCoolSetpointLimit>(), //
        make_unique<ReadThermostatMaxCoolSetpointLimit>(), //
        make_unique<WriteThermostatMaxCoolSetpointLimit>(), //
        make_unique<SubscribeAttributeThermostatMaxCoolSetpointLimit>(), //
        make_unique<ReadThermostatMinSetpointDeadBand>(), //
        make_unique<WriteThermostatMinSetpointDeadBand>(), //
        make_unique<SubscribeAttributeThermostatMinSetpointDeadBand>(), //
        make_unique<ReadThermostatRemoteSensing>(), //
        make_unique<WriteThermostatRemoteSensing>(), //
        make_unique<SubscribeAttributeThermostatRemoteSensing>(), //
        make_unique<ReadThermostatControlSequenceOfOperation>(), //
        make_unique<WriteThermostatControlSequenceOfOperation>(), //
        make_unique<SubscribeAttributeThermostatControlSequenceOfOperation>(), //
        make_unique<ReadThermostatSystemMode>(), //
        make_unique<WriteThermostatSystemMode>(), //
        make_unique<SubscribeAttributeThermostatSystemMode>(), //
        make_unique<ReadThermostatThermostatRunningMode>(), //
        make_unique<SubscribeAttributeThermostatThermostatRunningMode>(), //
        make_unique<ReadThermostatStartOfWeek>(), //
        make_unique<SubscribeAttributeThermostatStartOfWeek>(), //
        make_unique<ReadThermostatNumberOfWeeklyTransitions>(), //
        make_unique<SubscribeAttributeThermostatNumberOfWeeklyTransitions>(), //
        make_unique<ReadThermostatNumberOfDailyTransitions>(), //
        make_unique<SubscribeAttributeThermostatNumberOfDailyTransitions>(), //
        make_unique<ReadThermostatTemperatureSetpointHold>(), //
        make_unique<WriteThermostatTemperatureSetpointHold>(), //
        make_unique<SubscribeAttributeThermostatTemperatureSetpointHold>(), //
        make_unique<ReadThermostatTemperatureSetpointHoldDuration>(), //
        make_unique<WriteThermostatTemperatureSetpointHoldDuration>(), //
        make_unique<SubscribeAttributeThermostatTemperatureSetpointHoldDuration>(), //
        make_unique<ReadThermostatThermostatProgrammingOperationMode>(), //
        make_unique<WriteThermostatThermostatProgrammingOperationMode>(), //
        make_unique<SubscribeAttributeThermostatThermostatProgrammingOperationMode>(), //
        make_unique<ReadThermostatThermostatRunningState>(), //
        make_unique<SubscribeAttributeThermostatThermostatRunningState>(), //
        make_unique<ReadThermostatSetpointChangeSource>(), //
        make_unique<SubscribeAttributeThermostatSetpointChangeSource>(), //
        make_unique<ReadThermostatSetpointChangeAmount>(), //
        make_unique<SubscribeAttributeThermostatSetpointChangeAmount>(), //
        make_unique<ReadThermostatSetpointChangeSourceTimestamp>(), //
        make_unique<SubscribeAttributeThermostatSetpointChangeSourceTimestamp>(), //
        make_unique<ReadThermostatOccupiedSetback>(), //
        make_unique<WriteThermostatOccupiedSetback>(), //
        make_unique<SubscribeAttributeThermostatOccupiedSetback>(), //
        make_unique<ReadThermostatOccupiedSetbackMin>(), //
        make_unique<SubscribeAttributeThermostatOccupiedSetbackMin>(), //
        make_unique<ReadThermostatOccupiedSetbackMax>(), //
        make_unique<SubscribeAttributeThermostatOccupiedSetbackMax>(), //
        make_unique<ReadThermostatUnoccupiedSetback>(), //
        make_unique<WriteThermostatUnoccupiedSetback>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedSetback>(), //
        make_unique<ReadThermostatUnoccupiedSetbackMin>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedSetbackMin>(), //
        make_unique<ReadThermostatUnoccupiedSetbackMax>(), //
        make_unique<SubscribeAttributeThermostatUnoccupiedSetbackMax>(), //
        make_unique<ReadThermostatEmergencyHeatDelta>(), //
        make_unique<WriteThermostatEmergencyHeatDelta>(), //
        make_unique<SubscribeAttributeThermostatEmergencyHeatDelta>(), //
        make_unique<ReadThermostatACType>(), //
        make_unique<WriteThermostatACType>(), //
        make_unique<SubscribeAttributeThermostatACType>(), //
        make_unique<ReadThermostatACCapacity>(), //
        make_unique<WriteThermostatACCapacity>(), //
        make_unique<SubscribeAttributeThermostatACCapacity>(), //
        make_unique<ReadThermostatACRefrigerantType>(), //
        make_unique<WriteThermostatACRefrigerantType>(), //
        make_unique<SubscribeAttributeThermostatACRefrigerantType>(), //
        make_unique<ReadThermostatACCompressorType>(), //
        make_unique<WriteThermostatACCompressorType>(), //
        make_unique<SubscribeAttributeThermostatACCompressorType>(), //
        make_unique<ReadThermostatACErrorCode>(), //
        make_unique<WriteThermostatACErrorCode>(), //
        make_unique<SubscribeAttributeThermostatACErrorCode>(), //
        make_unique<ReadThermostatACLouverPosition>(), //
        make_unique<WriteThermostatACLouverPosition>(), //
        make_unique<SubscribeAttributeThermostatACLouverPosition>(), //
        make_unique<ReadThermostatACCoilTemperature>(), //
        make_unique<SubscribeAttributeThermostatACCoilTemperature>(), //
        make_unique<ReadThermostatACCapacityformat>(), //
        make_unique<WriteThermostatACCapacityformat>(), //
        make_unique<SubscribeAttributeThermostatACCapacityformat>(), //
        make_unique<ReadThermostatGeneratedCommandList>(), //
        make_unique<SubscribeAttributeThermostatGeneratedCommandList>(), //
        make_unique<ReadThermostatAcceptedCommandList>(), //
        make_unique<SubscribeAttributeThermostatAcceptedCommandList>(), //
        make_unique<ReadThermostatAttributeList>(), //
        make_unique<SubscribeAttributeThermostatAttributeList>(), //
        make_unique<ReadThermostatFeatureMap>(), //
        make_unique<SubscribeAttributeThermostatFeatureMap>(), //
        make_unique<ReadThermostatClusterRevision>(), //
        make_unique<SubscribeAttributeThermostatClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFanControl(Commands & commands)
{
    using namespace chip::app::Clusters::FanControl;

    const char * clusterName = "FanControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFanControlFanMode>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteFanControlFanMode>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFanControlFanMode>(), //
        make_unique<ReadFanControlFanModeSequence>(), //
        make_unique<WriteFanControlFanModeSequence>(), //
        make_unique<SubscribeAttributeFanControlFanModeSequence>(), //
        make_unique<ReadFanControlPercentSetting>(), //
        make_unique<WriteFanControlPercentSetting>(), //
        make_unique<SubscribeAttributeFanControlPercentSetting>(), //
        make_unique<ReadFanControlPercentCurrent>(), //
        make_unique<SubscribeAttributeFanControlPercentCurrent>(), //
        make_unique<ReadFanControlSpeedMax>(), //
        make_unique<SubscribeAttributeFanControlSpeedMax>(), //
        make_unique<ReadFanControlSpeedSetting>(), //
        make_unique<WriteFanControlSpeedSetting>(), //
        make_unique<SubscribeAttributeFanControlSpeedSetting>(), //
        make_unique<ReadFanControlSpeedCurrent>(), //
        make_unique<SubscribeAttributeFanControlSpeedCurrent>(), //
        make_unique<ReadFanControlRockSupport>(), //
        make_unique<SubscribeAttributeFanControlRockSupport>(), //
        make_unique<ReadFanControlRockSetting>(), //
        make_unique<WriteFanControlRockSetting>(), //
        make_unique<SubscribeAttributeFanControlRockSetting>(), //
        make_unique<ReadFanControlWindSupport>(), //
        make_unique<SubscribeAttributeFanControlWindSupport>(), //
        make_unique<ReadFanControlWindSetting>(), //
        make_unique<WriteFanControlWindSetting>(), //
        make_unique<SubscribeAttributeFanControlWindSetting>(), //
        make_unique<ReadFanControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFanControlGeneratedCommandList>(), //
        make_unique<ReadFanControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFanControlAcceptedCommandList>(), //
        make_unique<ReadFanControlAttributeList>(), //
        make_unique<SubscribeAttributeFanControlAttributeList>(), //
        make_unique<ReadFanControlFeatureMap>(), //
        make_unique<SubscribeAttributeFanControlFeatureMap>(), //
        make_unique<ReadFanControlClusterRevision>(), //
        make_unique<SubscribeAttributeFanControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterThermostatUserInterfaceConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::ThermostatUserInterfaceConfiguration;

    const char * clusterName = "ThermostatUserInterfaceConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadThermostatUserInterfaceConfigurationTemperatureDisplayMode>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteThermostatUserInterfaceConfigurationTemperatureDisplayMode>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationTemperatureDisplayMode>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationKeypadLockout>(), //
        make_unique<WriteThermostatUserInterfaceConfigurationKeypadLockout>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationKeypadLockout>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationScheduleProgrammingVisibility>(), //
        make_unique<WriteThermostatUserInterfaceConfigurationScheduleProgrammingVisibility>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationScheduleProgrammingVisibility>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationGeneratedCommandList>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationAcceptedCommandList>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationAttributeList>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationFeatureMap>(), //
        make_unique<ReadThermostatUserInterfaceConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeThermostatUserInterfaceConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterColorControl(Commands & commands)
{
    using namespace chip::app::Clusters::ColorControl;

    const char * clusterName = "ColorControl";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ColorControlMoveToHue>(), //
        make_unique<ColorControlMoveHue>(), //
        make_unique<ColorControlStepHue>(), //
        make_unique<ColorControlMoveToSaturation>(), //
        make_unique<ColorControlMoveSaturation>(), //
        make_unique<ColorControlStepSaturation>(), //
        make_unique<ColorControlMoveToHueAndSaturation>(), //
        make_unique<ColorControlMoveToColor>(), //
        make_unique<ColorControlMoveColor>(), //
        make_unique<ColorControlStepColor>(), //
        make_unique<ColorControlMoveToColorTemperature>(), //
        make_unique<ColorControlEnhancedMoveToHue>(), //
        make_unique<ColorControlEnhancedMoveHue>(), //
        make_unique<ColorControlEnhancedStepHue>(), //
        make_unique<ColorControlEnhancedMoveToHueAndSaturation>(), //
        make_unique<ColorControlColorLoopSet>(), //
        make_unique<ColorControlStopMoveStep>(), //
        make_unique<ColorControlMoveColorTemperature>(), //
        make_unique<ColorControlStepColorTemperature>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadColorControlCurrentHue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeColorControlCurrentHue>(), //
        make_unique<ReadColorControlCurrentSaturation>(), //
        make_unique<SubscribeAttributeColorControlCurrentSaturation>(), //
        make_unique<ReadColorControlRemainingTime>(), //
        make_unique<SubscribeAttributeColorControlRemainingTime>(), //
        make_unique<ReadColorControlCurrentX>(), //
        make_unique<SubscribeAttributeColorControlCurrentX>(), //
        make_unique<ReadColorControlCurrentY>(), //
        make_unique<SubscribeAttributeColorControlCurrentY>(), //
        make_unique<ReadColorControlDriftCompensation>(), //
        make_unique<SubscribeAttributeColorControlDriftCompensation>(), //
        make_unique<ReadColorControlCompensationText>(), //
        make_unique<SubscribeAttributeColorControlCompensationText>(), //
        make_unique<ReadColorControlColorTemperatureMireds>(), //
        make_unique<SubscribeAttributeColorControlColorTemperatureMireds>(), //
        make_unique<ReadColorControlColorMode>(), //
        make_unique<SubscribeAttributeColorControlColorMode>(), //
        make_unique<ReadColorControlOptions>(), //
        make_unique<WriteColorControlOptions>(), //
        make_unique<SubscribeAttributeColorControlOptions>(), //
        make_unique<ReadColorControlNumberOfPrimaries>(), //
        make_unique<SubscribeAttributeColorControlNumberOfPrimaries>(), //
        make_unique<ReadColorControlPrimary1X>(), //
        make_unique<SubscribeAttributeColorControlPrimary1X>(), //
        make_unique<ReadColorControlPrimary1Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary1Y>(), //
        make_unique<ReadColorControlPrimary1Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary1Intensity>(), //
        make_unique<ReadColorControlPrimary2X>(), //
        make_unique<SubscribeAttributeColorControlPrimary2X>(), //
        make_unique<ReadColorControlPrimary2Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary2Y>(), //
        make_unique<ReadColorControlPrimary2Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary2Intensity>(), //
        make_unique<ReadColorControlPrimary3X>(), //
        make_unique<SubscribeAttributeColorControlPrimary3X>(), //
        make_unique<ReadColorControlPrimary3Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary3Y>(), //
        make_unique<ReadColorControlPrimary3Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary3Intensity>(), //
        make_unique<ReadColorControlPrimary4X>(), //
        make_unique<SubscribeAttributeColorControlPrimary4X>(), //
        make_unique<ReadColorControlPrimary4Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary4Y>(), //
        make_unique<ReadColorControlPrimary4Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary4Intensity>(), //
        make_unique<ReadColorControlPrimary5X>(), //
        make_unique<SubscribeAttributeColorControlPrimary5X>(), //
        make_unique<ReadColorControlPrimary5Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary5Y>(), //
        make_unique<ReadColorControlPrimary5Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary5Intensity>(), //
        make_unique<ReadColorControlPrimary6X>(), //
        make_unique<SubscribeAttributeColorControlPrimary6X>(), //
        make_unique<ReadColorControlPrimary6Y>(), //
        make_unique<SubscribeAttributeColorControlPrimary6Y>(), //
        make_unique<ReadColorControlPrimary6Intensity>(), //
        make_unique<SubscribeAttributeColorControlPrimary6Intensity>(), //
        make_unique<ReadColorControlWhitePointX>(), //
        make_unique<WriteColorControlWhitePointX>(), //
        make_unique<SubscribeAttributeColorControlWhitePointX>(), //
        make_unique<ReadColorControlWhitePointY>(), //
        make_unique<WriteColorControlWhitePointY>(), //
        make_unique<SubscribeAttributeColorControlWhitePointY>(), //
        make_unique<ReadColorControlColorPointRX>(), //
        make_unique<WriteColorControlColorPointRX>(), //
        make_unique<SubscribeAttributeColorControlColorPointRX>(), //
        make_unique<ReadColorControlColorPointRY>(), //
        make_unique<WriteColorControlColorPointRY>(), //
        make_unique<SubscribeAttributeColorControlColorPointRY>(), //
        make_unique<ReadColorControlColorPointRIntensity>(), //
        make_unique<WriteColorControlColorPointRIntensity>(), //
        make_unique<SubscribeAttributeColorControlColorPointRIntensity>(), //
        make_unique<ReadColorControlColorPointGX>(), //
        make_unique<WriteColorControlColorPointGX>(), //
        make_unique<SubscribeAttributeColorControlColorPointGX>(), //
        make_unique<ReadColorControlColorPointGY>(), //
        make_unique<WriteColorControlColorPointGY>(), //
        make_unique<SubscribeAttributeColorControlColorPointGY>(), //
        make_unique<ReadColorControlColorPointGIntensity>(), //
        make_unique<WriteColorControlColorPointGIntensity>(), //
        make_unique<SubscribeAttributeColorControlColorPointGIntensity>(), //
        make_unique<ReadColorControlColorPointBX>(), //
        make_unique<WriteColorControlColorPointBX>(), //
        make_unique<SubscribeAttributeColorControlColorPointBX>(), //
        make_unique<ReadColorControlColorPointBY>(), //
        make_unique<WriteColorControlColorPointBY>(), //
        make_unique<SubscribeAttributeColorControlColorPointBY>(), //
        make_unique<ReadColorControlColorPointBIntensity>(), //
        make_unique<WriteColorControlColorPointBIntensity>(), //
        make_unique<SubscribeAttributeColorControlColorPointBIntensity>(), //
        make_unique<ReadColorControlEnhancedCurrentHue>(), //
        make_unique<SubscribeAttributeColorControlEnhancedCurrentHue>(), //
        make_unique<ReadColorControlEnhancedColorMode>(), //
        make_unique<SubscribeAttributeColorControlEnhancedColorMode>(), //
        make_unique<ReadColorControlColorLoopActive>(), //
        make_unique<SubscribeAttributeColorControlColorLoopActive>(), //
        make_unique<ReadColorControlColorLoopDirection>(), //
        make_unique<SubscribeAttributeColorControlColorLoopDirection>(), //
        make_unique<ReadColorControlColorLoopTime>(), //
        make_unique<SubscribeAttributeColorControlColorLoopTime>(), //
        make_unique<ReadColorControlColorLoopStartEnhancedHue>(), //
        make_unique<SubscribeAttributeColorControlColorLoopStartEnhancedHue>(), //
        make_unique<ReadColorControlColorLoopStoredEnhancedHue>(), //
        make_unique<SubscribeAttributeColorControlColorLoopStoredEnhancedHue>(), //
        make_unique<ReadColorControlColorCapabilities>(), //
        make_unique<SubscribeAttributeColorControlColorCapabilities>(), //
        make_unique<ReadColorControlColorTempPhysicalMinMireds>(), //
        make_unique<SubscribeAttributeColorControlColorTempPhysicalMinMireds>(), //
        make_unique<ReadColorControlColorTempPhysicalMaxMireds>(), //
        make_unique<SubscribeAttributeColorControlColorTempPhysicalMaxMireds>(), //
        make_unique<ReadColorControlCoupleColorTempToLevelMinMireds>(), //
        make_unique<SubscribeAttributeColorControlCoupleColorTempToLevelMinMireds>(), //
        make_unique<ReadColorControlStartUpColorTemperatureMireds>(), //
        make_unique<WriteColorControlStartUpColorTemperatureMireds>(), //
        make_unique<SubscribeAttributeColorControlStartUpColorTemperatureMireds>(), //
        make_unique<ReadColorControlGeneratedCommandList>(), //
        make_unique<SubscribeAttributeColorControlGeneratedCommandList>(), //
        make_unique<ReadColorControlAcceptedCommandList>(), //
        make_unique<SubscribeAttributeColorControlAcceptedCommandList>(), //
        make_unique<ReadColorControlAttributeList>(), //
        make_unique<SubscribeAttributeColorControlAttributeList>(), //
        make_unique<ReadColorControlFeatureMap>(), //
        make_unique<SubscribeAttributeColorControlFeatureMap>(), //
        make_unique<ReadColorControlClusterRevision>(), //
        make_unique<SubscribeAttributeColorControlClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterBallastConfiguration(Commands & commands)
{
    using namespace chip::app::Clusters::BallastConfiguration;

    const char * clusterName = "BallastConfiguration";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadBallastConfigurationPhysicalMinLevel>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeBallastConfigurationPhysicalMinLevel>(), //
        make_unique<ReadBallastConfigurationPhysicalMaxLevel>(), //
        make_unique<SubscribeAttributeBallastConfigurationPhysicalMaxLevel>(), //
        make_unique<ReadBallastConfigurationBallastStatus>(), //
        make_unique<SubscribeAttributeBallastConfigurationBallastStatus>(), //
        make_unique<ReadBallastConfigurationMinLevel>(), //
        make_unique<WriteBallastConfigurationMinLevel>(), //
        make_unique<SubscribeAttributeBallastConfigurationMinLevel>(), //
        make_unique<ReadBallastConfigurationMaxLevel>(), //
        make_unique<WriteBallastConfigurationMaxLevel>(), //
        make_unique<SubscribeAttributeBallastConfigurationMaxLevel>(), //
        make_unique<ReadBallastConfigurationIntrinsicBalanceFactor>(), //
        make_unique<WriteBallastConfigurationIntrinsicBalanceFactor>(), //
        make_unique<SubscribeAttributeBallastConfigurationIntrinsicBalanceFactor>(), //
        make_unique<ReadBallastConfigurationBallastFactorAdjustment>(), //
        make_unique<WriteBallastConfigurationBallastFactorAdjustment>(), //
        make_unique<SubscribeAttributeBallastConfigurationBallastFactorAdjustment>(), //
        make_unique<ReadBallastConfigurationLampQuantity>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampQuantity>(), //
        make_unique<ReadBallastConfigurationLampType>(), //
        make_unique<WriteBallastConfigurationLampType>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampType>(), //
        make_unique<ReadBallastConfigurationLampManufacturer>(), //
        make_unique<WriteBallastConfigurationLampManufacturer>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampManufacturer>(), //
        make_unique<ReadBallastConfigurationLampRatedHours>(), //
        make_unique<WriteBallastConfigurationLampRatedHours>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampRatedHours>(), //
        make_unique<ReadBallastConfigurationLampBurnHours>(), //
        make_unique<WriteBallastConfigurationLampBurnHours>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampBurnHours>(), //
        make_unique<ReadBallastConfigurationLampAlarmMode>(), //
        make_unique<WriteBallastConfigurationLampAlarmMode>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampAlarmMode>(), //
        make_unique<ReadBallastConfigurationLampBurnHoursTripPoint>(), //
        make_unique<WriteBallastConfigurationLampBurnHoursTripPoint>(), //
        make_unique<SubscribeAttributeBallastConfigurationLampBurnHoursTripPoint>(), //
        make_unique<ReadBallastConfigurationGeneratedCommandList>(), //
        make_unique<SubscribeAttributeBallastConfigurationGeneratedCommandList>(), //
        make_unique<ReadBallastConfigurationAcceptedCommandList>(), //
        make_unique<SubscribeAttributeBallastConfigurationAcceptedCommandList>(), //
        make_unique<ReadBallastConfigurationAttributeList>(), //
        make_unique<SubscribeAttributeBallastConfigurationAttributeList>(), //
        make_unique<ReadBallastConfigurationFeatureMap>(), //
        make_unique<SubscribeAttributeBallastConfigurationFeatureMap>(), //
        make_unique<ReadBallastConfigurationClusterRevision>(), //
        make_unique<SubscribeAttributeBallastConfigurationClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterIlluminanceMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::IlluminanceMeasurement;

    const char * clusterName = "IlluminanceMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadIlluminanceMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeIlluminanceMeasurementMeasuredValue>(), //
        make_unique<ReadIlluminanceMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementMinMeasuredValue>(), //
        make_unique<ReadIlluminanceMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementMaxMeasuredValue>(), //
        make_unique<ReadIlluminanceMeasurementTolerance>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementTolerance>(), //
        make_unique<ReadIlluminanceMeasurementLightSensorType>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementLightSensorType>(), //
        make_unique<ReadIlluminanceMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementGeneratedCommandList>(), //
        make_unique<ReadIlluminanceMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementAcceptedCommandList>(), //
        make_unique<ReadIlluminanceMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementAttributeList>(), //
        make_unique<ReadIlluminanceMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementFeatureMap>(), //
        make_unique<ReadIlluminanceMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeIlluminanceMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTemperatureMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::TemperatureMeasurement;

    const char * clusterName = "TemperatureMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTemperatureMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTemperatureMeasurementMeasuredValue>(), //
        make_unique<ReadTemperatureMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementMinMeasuredValue>(), //
        make_unique<ReadTemperatureMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementMaxMeasuredValue>(), //
        make_unique<ReadTemperatureMeasurementTolerance>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementTolerance>(), //
        make_unique<ReadTemperatureMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementGeneratedCommandList>(), //
        make_unique<ReadTemperatureMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementAcceptedCommandList>(), //
        make_unique<ReadTemperatureMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementAttributeList>(), //
        make_unique<ReadTemperatureMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementFeatureMap>(), //
        make_unique<ReadTemperatureMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeTemperatureMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterPressureMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::PressureMeasurement;

    const char * clusterName = "PressureMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadPressureMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributePressureMeasurementMeasuredValue>(), //
        make_unique<ReadPressureMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMinMeasuredValue>(), //
        make_unique<ReadPressureMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMaxMeasuredValue>(), //
        make_unique<ReadPressureMeasurementTolerance>(), //
        make_unique<SubscribeAttributePressureMeasurementTolerance>(), //
        make_unique<ReadPressureMeasurementScaledValue>(), //
        make_unique<SubscribeAttributePressureMeasurementScaledValue>(), //
        make_unique<ReadPressureMeasurementMinScaledValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMinScaledValue>(), //
        make_unique<ReadPressureMeasurementMaxScaledValue>(), //
        make_unique<SubscribeAttributePressureMeasurementMaxScaledValue>(), //
        make_unique<ReadPressureMeasurementScaledTolerance>(), //
        make_unique<SubscribeAttributePressureMeasurementScaledTolerance>(), //
        make_unique<ReadPressureMeasurementScale>(), //
        make_unique<SubscribeAttributePressureMeasurementScale>(), //
        make_unique<ReadPressureMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributePressureMeasurementGeneratedCommandList>(), //
        make_unique<ReadPressureMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributePressureMeasurementAcceptedCommandList>(), //
        make_unique<ReadPressureMeasurementAttributeList>(), //
        make_unique<SubscribeAttributePressureMeasurementAttributeList>(), //
        make_unique<ReadPressureMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributePressureMeasurementFeatureMap>(), //
        make_unique<ReadPressureMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributePressureMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterFlowMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::FlowMeasurement;

    const char * clusterName = "FlowMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadFlowMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeFlowMeasurementMeasuredValue>(), //
        make_unique<ReadFlowMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeFlowMeasurementMinMeasuredValue>(), //
        make_unique<ReadFlowMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeFlowMeasurementMaxMeasuredValue>(), //
        make_unique<ReadFlowMeasurementTolerance>(), //
        make_unique<SubscribeAttributeFlowMeasurementTolerance>(), //
        make_unique<ReadFlowMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeFlowMeasurementGeneratedCommandList>(), //
        make_unique<ReadFlowMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeFlowMeasurementAcceptedCommandList>(), //
        make_unique<ReadFlowMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeFlowMeasurementAttributeList>(), //
        make_unique<ReadFlowMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeFlowMeasurementFeatureMap>(), //
        make_unique<ReadFlowMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeFlowMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterRelativeHumidityMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::RelativeHumidityMeasurement;

    const char * clusterName = "RelativeHumidityMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadRelativeHumidityMeasurementMeasuredValue>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementMeasuredValue>(), //
        make_unique<ReadRelativeHumidityMeasurementMinMeasuredValue>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementMinMeasuredValue>(), //
        make_unique<ReadRelativeHumidityMeasurementMaxMeasuredValue>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementMaxMeasuredValue>(), //
        make_unique<ReadRelativeHumidityMeasurementTolerance>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementTolerance>(), //
        make_unique<ReadRelativeHumidityMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementGeneratedCommandList>(), //
        make_unique<ReadRelativeHumidityMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementAcceptedCommandList>(), //
        make_unique<ReadRelativeHumidityMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementAttributeList>(), //
        make_unique<ReadRelativeHumidityMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementFeatureMap>(), //
        make_unique<ReadRelativeHumidityMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeRelativeHumidityMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterOccupancySensing(Commands & commands)
{
    using namespace chip::app::Clusters::OccupancySensing;

    const char * clusterName = "OccupancySensing";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadOccupancySensingOccupancy>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeOccupancySensingOccupancy>(), //
        make_unique<ReadOccupancySensingOccupancySensorType>(), //
        make_unique<SubscribeAttributeOccupancySensingOccupancySensorType>(), //
        make_unique<ReadOccupancySensingOccupancySensorTypeBitmap>(), //
        make_unique<SubscribeAttributeOccupancySensingOccupancySensorTypeBitmap>(), //
        make_unique<ReadOccupancySensingPirOccupiedToUnoccupiedDelay>(), //
        make_unique<WriteOccupancySensingPirOccupiedToUnoccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPirOccupiedToUnoccupiedDelay>(), //
        make_unique<ReadOccupancySensingPirUnoccupiedToOccupiedDelay>(), //
        make_unique<WriteOccupancySensingPirUnoccupiedToOccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedDelay>(), //
        make_unique<ReadOccupancySensingPirUnoccupiedToOccupiedThreshold>(), //
        make_unique<WriteOccupancySensingPirUnoccupiedToOccupiedThreshold>(), //
        make_unique<SubscribeAttributeOccupancySensingPirUnoccupiedToOccupiedThreshold>(), //
        make_unique<ReadOccupancySensingUltrasonicOccupiedToUnoccupiedDelay>(), //
        make_unique<WriteOccupancySensingUltrasonicOccupiedToUnoccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingUltrasonicOccupiedToUnoccupiedDelay>(), //
        make_unique<ReadOccupancySensingUltrasonicUnoccupiedToOccupiedDelay>(), //
        make_unique<WriteOccupancySensingUltrasonicUnoccupiedToOccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedDelay>(), //
        make_unique<ReadOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold>(), //
        make_unique<WriteOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold>(), //
        make_unique<SubscribeAttributeOccupancySensingUltrasonicUnoccupiedToOccupiedThreshold>(), //
        make_unique<ReadOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay>(), //
        make_unique<WriteOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPhysicalContactOccupiedToUnoccupiedDelay>(), //
        make_unique<ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay>(), //
        make_unique<WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay>(), //
        make_unique<SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedDelay>(), //
        make_unique<ReadOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold>(), //
        make_unique<WriteOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold>(), //
        make_unique<SubscribeAttributeOccupancySensingPhysicalContactUnoccupiedToOccupiedThreshold>(), //
        make_unique<ReadOccupancySensingGeneratedCommandList>(), //
        make_unique<SubscribeAttributeOccupancySensingGeneratedCommandList>(), //
        make_unique<ReadOccupancySensingAcceptedCommandList>(), //
        make_unique<SubscribeAttributeOccupancySensingAcceptedCommandList>(), //
        make_unique<ReadOccupancySensingAttributeList>(), //
        make_unique<SubscribeAttributeOccupancySensingAttributeList>(), //
        make_unique<ReadOccupancySensingFeatureMap>(), //
        make_unique<SubscribeAttributeOccupancySensingFeatureMap>(), //
        make_unique<ReadOccupancySensingClusterRevision>(), //
        make_unique<SubscribeAttributeOccupancySensingClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterWakeOnLan(Commands & commands)
{
    using namespace chip::app::Clusters::WakeOnLan;

    const char * clusterName = "WakeOnLan";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadWakeOnLanMACAddress>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeWakeOnLanMACAddress>(), //
        make_unique<ReadWakeOnLanGeneratedCommandList>(), //
        make_unique<SubscribeAttributeWakeOnLanGeneratedCommandList>(), //
        make_unique<ReadWakeOnLanAcceptedCommandList>(), //
        make_unique<SubscribeAttributeWakeOnLanAcceptedCommandList>(), //
        make_unique<ReadWakeOnLanAttributeList>(), //
        make_unique<SubscribeAttributeWakeOnLanAttributeList>(), //
        make_unique<ReadWakeOnLanFeatureMap>(), //
        make_unique<SubscribeAttributeWakeOnLanFeatureMap>(), //
        make_unique<ReadWakeOnLanClusterRevision>(), //
        make_unique<SubscribeAttributeWakeOnLanClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterChannel(Commands & commands)
{
    using namespace chip::app::Clusters::Channel;

    const char * clusterName = "Channel";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ChannelChangeChannel>(), //
        make_unique<ChannelChangeChannelByNumber>(), //
        make_unique<ChannelSkipChannel>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadChannelChannelList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeChannelChannelList>(), //
        make_unique<ReadChannelLineup>(), //
        make_unique<SubscribeAttributeChannelLineup>(), //
        make_unique<ReadChannelCurrentChannel>(), //
        make_unique<SubscribeAttributeChannelCurrentChannel>(), //
        make_unique<ReadChannelGeneratedCommandList>(), //
        make_unique<SubscribeAttributeChannelGeneratedCommandList>(), //
        make_unique<ReadChannelAcceptedCommandList>(), //
        make_unique<SubscribeAttributeChannelAcceptedCommandList>(), //
        make_unique<ReadChannelAttributeList>(), //
        make_unique<SubscribeAttributeChannelAttributeList>(), //
        make_unique<ReadChannelFeatureMap>(), //
        make_unique<SubscribeAttributeChannelFeatureMap>(), //
        make_unique<ReadChannelClusterRevision>(), //
        make_unique<SubscribeAttributeChannelClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTargetNavigator(Commands & commands)
{
    using namespace chip::app::Clusters::TargetNavigator;

    const char * clusterName = "TargetNavigator";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<TargetNavigatorNavigateTarget>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTargetNavigatorTargetList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTargetNavigatorTargetList>(), //
        make_unique<ReadTargetNavigatorCurrentTarget>(), //
        make_unique<SubscribeAttributeTargetNavigatorCurrentTarget>(), //
        make_unique<ReadTargetNavigatorGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTargetNavigatorGeneratedCommandList>(), //
        make_unique<ReadTargetNavigatorAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTargetNavigatorAcceptedCommandList>(), //
        make_unique<ReadTargetNavigatorAttributeList>(), //
        make_unique<SubscribeAttributeTargetNavigatorAttributeList>(), //
        make_unique<ReadTargetNavigatorFeatureMap>(), //
        make_unique<SubscribeAttributeTargetNavigatorFeatureMap>(), //
        make_unique<ReadTargetNavigatorClusterRevision>(), //
        make_unique<SubscribeAttributeTargetNavigatorClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterMediaPlayback(Commands & commands)
{
    using namespace chip::app::Clusters::MediaPlayback;

    const char * clusterName = "MediaPlayback";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<MediaPlaybackPlay>(), //
        make_unique<MediaPlaybackPause>(), //
        make_unique<MediaPlaybackStopPlayback>(), //
        make_unique<MediaPlaybackStartOver>(), //
        make_unique<MediaPlaybackPrevious>(), //
        make_unique<MediaPlaybackNext>(), //
        make_unique<MediaPlaybackRewind>(), //
        make_unique<MediaPlaybackFastForward>(), //
        make_unique<MediaPlaybackSkipForward>(), //
        make_unique<MediaPlaybackSkipBackward>(), //
        make_unique<MediaPlaybackSeek>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadMediaPlaybackCurrentState>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeMediaPlaybackCurrentState>(), //
        make_unique<ReadMediaPlaybackStartTime>(), //
        make_unique<SubscribeAttributeMediaPlaybackStartTime>(), //
        make_unique<ReadMediaPlaybackDuration>(), //
        make_unique<SubscribeAttributeMediaPlaybackDuration>(), //
        make_unique<ReadMediaPlaybackSampledPosition>(), //
        make_unique<SubscribeAttributeMediaPlaybackSampledPosition>(), //
        make_unique<ReadMediaPlaybackPlaybackSpeed>(), //
        make_unique<SubscribeAttributeMediaPlaybackPlaybackSpeed>(), //
        make_unique<ReadMediaPlaybackSeekRangeEnd>(), //
        make_unique<SubscribeAttributeMediaPlaybackSeekRangeEnd>(), //
        make_unique<ReadMediaPlaybackSeekRangeStart>(), //
        make_unique<SubscribeAttributeMediaPlaybackSeekRangeStart>(), //
        make_unique<ReadMediaPlaybackGeneratedCommandList>(), //
        make_unique<SubscribeAttributeMediaPlaybackGeneratedCommandList>(), //
        make_unique<ReadMediaPlaybackAcceptedCommandList>(), //
        make_unique<SubscribeAttributeMediaPlaybackAcceptedCommandList>(), //
        make_unique<ReadMediaPlaybackAttributeList>(), //
        make_unique<SubscribeAttributeMediaPlaybackAttributeList>(), //
        make_unique<ReadMediaPlaybackFeatureMap>(), //
        make_unique<SubscribeAttributeMediaPlaybackFeatureMap>(), //
        make_unique<ReadMediaPlaybackClusterRevision>(), //
        make_unique<SubscribeAttributeMediaPlaybackClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterMediaInput(Commands & commands)
{
    using namespace chip::app::Clusters::MediaInput;

    const char * clusterName = "MediaInput";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<MediaInputSelectInput>(), //
        make_unique<MediaInputShowInputStatus>(), //
        make_unique<MediaInputHideInputStatus>(), //
        make_unique<MediaInputRenameInput>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadMediaInputInputList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeMediaInputInputList>(), //
        make_unique<ReadMediaInputCurrentInput>(), //
        make_unique<SubscribeAttributeMediaInputCurrentInput>(), //
        make_unique<ReadMediaInputGeneratedCommandList>(), //
        make_unique<SubscribeAttributeMediaInputGeneratedCommandList>(), //
        make_unique<ReadMediaInputAcceptedCommandList>(), //
        make_unique<SubscribeAttributeMediaInputAcceptedCommandList>(), //
        make_unique<ReadMediaInputAttributeList>(), //
        make_unique<SubscribeAttributeMediaInputAttributeList>(), //
        make_unique<ReadMediaInputFeatureMap>(), //
        make_unique<SubscribeAttributeMediaInputFeatureMap>(), //
        make_unique<ReadMediaInputClusterRevision>(), //
        make_unique<SubscribeAttributeMediaInputClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterLowPower(Commands & commands)
{
    using namespace chip::app::Clusters::LowPower;

    const char * clusterName = "LowPower";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<LowPowerSleep>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadLowPowerGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeLowPowerGeneratedCommandList>(), //
        make_unique<ReadLowPowerAcceptedCommandList>(), //
        make_unique<SubscribeAttributeLowPowerAcceptedCommandList>(), //
        make_unique<ReadLowPowerAttributeList>(), //
        make_unique<SubscribeAttributeLowPowerAttributeList>(), //
        make_unique<ReadLowPowerFeatureMap>(), //
        make_unique<SubscribeAttributeLowPowerFeatureMap>(), //
        make_unique<ReadLowPowerClusterRevision>(), //
        make_unique<SubscribeAttributeLowPowerClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterKeypadInput(Commands & commands)
{
    using namespace chip::app::Clusters::KeypadInput;

    const char * clusterName = "KeypadInput";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<KeypadInputSendKey>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadKeypadInputGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeKeypadInputGeneratedCommandList>(), //
        make_unique<ReadKeypadInputAcceptedCommandList>(), //
        make_unique<SubscribeAttributeKeypadInputAcceptedCommandList>(), //
        make_unique<ReadKeypadInputAttributeList>(), //
        make_unique<SubscribeAttributeKeypadInputAttributeList>(), //
        make_unique<ReadKeypadInputFeatureMap>(), //
        make_unique<SubscribeAttributeKeypadInputFeatureMap>(), //
        make_unique<ReadKeypadInputClusterRevision>(), //
        make_unique<SubscribeAttributeKeypadInputClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterContentLauncher(Commands & commands)
{
    using namespace chip::app::Clusters::ContentLauncher;

    const char * clusterName = "ContentLauncher";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ContentLauncherLaunchContent>(), //
        make_unique<ContentLauncherLaunchURL>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadContentLauncherAcceptHeader>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeContentLauncherAcceptHeader>(), //
        make_unique<ReadContentLauncherSupportedStreamingProtocols>(), //
        make_unique<WriteContentLauncherSupportedStreamingProtocols>(), //
        make_unique<SubscribeAttributeContentLauncherSupportedStreamingProtocols>(), //
        make_unique<ReadContentLauncherGeneratedCommandList>(), //
        make_unique<SubscribeAttributeContentLauncherGeneratedCommandList>(), //
        make_unique<ReadContentLauncherAcceptedCommandList>(), //
        make_unique<SubscribeAttributeContentLauncherAcceptedCommandList>(), //
        make_unique<ReadContentLauncherAttributeList>(), //
        make_unique<SubscribeAttributeContentLauncherAttributeList>(), //
        make_unique<ReadContentLauncherFeatureMap>(), //
        make_unique<SubscribeAttributeContentLauncherFeatureMap>(), //
        make_unique<ReadContentLauncherClusterRevision>(), //
        make_unique<SubscribeAttributeContentLauncherClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAudioOutput(Commands & commands)
{
    using namespace chip::app::Clusters::AudioOutput;

    const char * clusterName = "AudioOutput";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<AudioOutputSelectOutput>(), //
        make_unique<AudioOutputRenameOutput>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAudioOutputOutputList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAudioOutputOutputList>(), //
        make_unique<ReadAudioOutputCurrentOutput>(), //
        make_unique<SubscribeAttributeAudioOutputCurrentOutput>(), //
        make_unique<ReadAudioOutputGeneratedCommandList>(), //
        make_unique<SubscribeAttributeAudioOutputGeneratedCommandList>(), //
        make_unique<ReadAudioOutputAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAudioOutputAcceptedCommandList>(), //
        make_unique<ReadAudioOutputAttributeList>(), //
        make_unique<SubscribeAttributeAudioOutputAttributeList>(), //
        make_unique<ReadAudioOutputFeatureMap>(), //
        make_unique<SubscribeAttributeAudioOutputFeatureMap>(), //
        make_unique<ReadAudioOutputClusterRevision>(), //
        make_unique<SubscribeAttributeAudioOutputClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterApplicationLauncher(Commands & commands)
{
    using namespace chip::app::Clusters::ApplicationLauncher;

    const char * clusterName = "ApplicationLauncher";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ApplicationLauncherLaunchApp>(), //
        make_unique<ApplicationLauncherStopApp>(), //
        make_unique<ApplicationLauncherHideApp>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadApplicationLauncherCatalogList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeApplicationLauncherCatalogList>(), //
        make_unique<ReadApplicationLauncherCurrentApp>(), //
        make_unique<WriteApplicationLauncherCurrentApp>(), //
        make_unique<SubscribeAttributeApplicationLauncherCurrentApp>(), //
        make_unique<ReadApplicationLauncherGeneratedCommandList>(), //
        make_unique<SubscribeAttributeApplicationLauncherGeneratedCommandList>(), //
        make_unique<ReadApplicationLauncherAcceptedCommandList>(), //
        make_unique<SubscribeAttributeApplicationLauncherAcceptedCommandList>(), //
        make_unique<ReadApplicationLauncherAttributeList>(), //
        make_unique<SubscribeAttributeApplicationLauncherAttributeList>(), //
        make_unique<ReadApplicationLauncherFeatureMap>(), //
        make_unique<SubscribeAttributeApplicationLauncherFeatureMap>(), //
        make_unique<ReadApplicationLauncherClusterRevision>(), //
        make_unique<SubscribeAttributeApplicationLauncherClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterApplicationBasic(Commands & commands)
{
    using namespace chip::app::Clusters::ApplicationBasic;

    const char * clusterName = "ApplicationBasic";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadApplicationBasicVendorName>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeApplicationBasicVendorName>(), //
        make_unique<ReadApplicationBasicVendorID>(), //
        make_unique<SubscribeAttributeApplicationBasicVendorID>(), //
        make_unique<ReadApplicationBasicApplicationName>(), //
        make_unique<SubscribeAttributeApplicationBasicApplicationName>(), //
        make_unique<ReadApplicationBasicProductID>(), //
        make_unique<SubscribeAttributeApplicationBasicProductID>(), //
        make_unique<ReadApplicationBasicApplication>(), //
        make_unique<SubscribeAttributeApplicationBasicApplication>(), //
        make_unique<ReadApplicationBasicStatus>(), //
        make_unique<SubscribeAttributeApplicationBasicStatus>(), //
        make_unique<ReadApplicationBasicApplicationVersion>(), //
        make_unique<SubscribeAttributeApplicationBasicApplicationVersion>(), //
        make_unique<ReadApplicationBasicAllowedVendorList>(), //
        make_unique<SubscribeAttributeApplicationBasicAllowedVendorList>(), //
        make_unique<ReadApplicationBasicGeneratedCommandList>(), //
        make_unique<SubscribeAttributeApplicationBasicGeneratedCommandList>(), //
        make_unique<ReadApplicationBasicAcceptedCommandList>(), //
        make_unique<SubscribeAttributeApplicationBasicAcceptedCommandList>(), //
        make_unique<ReadApplicationBasicAttributeList>(), //
        make_unique<SubscribeAttributeApplicationBasicAttributeList>(), //
        make_unique<ReadApplicationBasicFeatureMap>(), //
        make_unique<SubscribeAttributeApplicationBasicFeatureMap>(), //
        make_unique<ReadApplicationBasicClusterRevision>(), //
        make_unique<SubscribeAttributeApplicationBasicClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterAccountLogin(Commands & commands)
{
    using namespace chip::app::Clusters::AccountLogin;

    const char * clusterName = "AccountLogin";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<AccountLoginGetSetupPIN>(), //
        make_unique<AccountLoginLogin>(), //
        make_unique<AccountLoginLogout>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadAccountLoginGeneratedCommandList>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeAccountLoginGeneratedCommandList>(), //
        make_unique<ReadAccountLoginAcceptedCommandList>(), //
        make_unique<SubscribeAttributeAccountLoginAcceptedCommandList>(), //
        make_unique<ReadAccountLoginAttributeList>(), //
        make_unique<SubscribeAttributeAccountLoginAttributeList>(), //
        make_unique<ReadAccountLoginFeatureMap>(), //
        make_unique<SubscribeAttributeAccountLoginFeatureMap>(), //
        make_unique<ReadAccountLoginClusterRevision>(), //
        make_unique<SubscribeAttributeAccountLoginClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterElectricalMeasurement(Commands & commands)
{
    using namespace chip::app::Clusters::ElectricalMeasurement;

    const char * clusterName = "ElectricalMeasurement";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<ElectricalMeasurementGetProfileInfoCommand>(), //
        make_unique<ElectricalMeasurementGetMeasurementProfileCommand>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadElectricalMeasurementMeasurementType>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasurementType>(), //
        make_unique<ReadElectricalMeasurementDcVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltage>(), //
        make_unique<ReadElectricalMeasurementDcVoltageMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageMin>(), //
        make_unique<ReadElectricalMeasurementDcVoltageMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageMax>(), //
        make_unique<ReadElectricalMeasurementDcCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrent>(), //
        make_unique<ReadElectricalMeasurementDcCurrentMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentMin>(), //
        make_unique<ReadElectricalMeasurementDcCurrentMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentMax>(), //
        make_unique<ReadElectricalMeasurementDcPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPower>(), //
        make_unique<ReadElectricalMeasurementDcPowerMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerMin>(), //
        make_unique<ReadElectricalMeasurementDcPowerMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerMax>(), //
        make_unique<ReadElectricalMeasurementDcVoltageMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageMultiplier>(), //
        make_unique<ReadElectricalMeasurementDcVoltageDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcVoltageDivisor>(), //
        make_unique<ReadElectricalMeasurementDcCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementDcCurrentDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcCurrentDivisor>(), //
        make_unique<ReadElectricalMeasurementDcPowerMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerMultiplier>(), //
        make_unique<ReadElectricalMeasurementDcPowerDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementDcPowerDivisor>(), //
        make_unique<ReadElectricalMeasurementAcFrequency>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequency>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyMin>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyMax>(), //
        make_unique<ReadElectricalMeasurementNeutralCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementNeutralCurrent>(), //
        make_unique<ReadElectricalMeasurementTotalActivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementTotalActivePower>(), //
        make_unique<ReadElectricalMeasurementTotalReactivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementTotalReactivePower>(), //
        make_unique<ReadElectricalMeasurementTotalApparentPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementTotalApparentPower>(), //
        make_unique<ReadElectricalMeasurementMeasured1stHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured1stHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured3rdHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured3rdHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured5thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured5thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured7thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured7thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured9thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured9thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasured11thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasured11thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase1stHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase1stHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase3rdHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase3rdHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase5thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase5thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase7thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase7thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase9thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase9thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementMeasuredPhase11thHarmonicCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementMeasuredPhase11thHarmonicCurrent>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcFrequencyDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcFrequencyDivisor>(), //
        make_unique<ReadElectricalMeasurementPowerMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerMultiplier>(), //
        make_unique<ReadElectricalMeasurementPowerDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerDivisor>(), //
        make_unique<ReadElectricalMeasurementHarmonicCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementHarmonicCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementPhaseHarmonicCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPhaseHarmonicCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementInstantaneousVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousVoltage>(), //
        make_unique<ReadElectricalMeasurementInstantaneousLineCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousLineCurrent>(), //
        make_unique<ReadElectricalMeasurementInstantaneousActiveCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousActiveCurrent>(), //
        make_unique<ReadElectricalMeasurementInstantaneousReactiveCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousReactiveCurrent>(), //
        make_unique<ReadElectricalMeasurementInstantaneousPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementInstantaneousPower>(), //
        make_unique<ReadElectricalMeasurementRmsVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMin>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMax>(), //
        make_unique<ReadElectricalMeasurementRmsCurrent>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrent>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMin>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMax>(), //
        make_unique<ReadElectricalMeasurementActivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePower>(), //
        make_unique<ReadElectricalMeasurementActivePowerMin>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMin>(), //
        make_unique<ReadElectricalMeasurementActivePowerMax>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMax>(), //
        make_unique<ReadElectricalMeasurementReactivePower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactivePower>(), //
        make_unique<ReadElectricalMeasurementApparentPower>(), //
        make_unique<SubscribeAttributeElectricalMeasurementApparentPower>(), //
        make_unique<ReadElectricalMeasurementPowerFactor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerFactor>(), //
        make_unique<ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriod>(), //
        make_unique<WriteElectricalMeasurementAverageRmsVoltageMeasurementPeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriod>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltageCounter>(), //
        make_unique<WriteElectricalMeasurementAverageRmsUnderVoltageCounter>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounter>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltagePeriod>(), //
        make_unique<WriteElectricalMeasurementRmsExtremeOverVoltagePeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriod>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltagePeriod>(), //
        make_unique<WriteElectricalMeasurementRmsExtremeUnderVoltagePeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriod>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSagPeriod>(), //
        make_unique<WriteElectricalMeasurementRmsVoltageSagPeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriod>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwellPeriod>(), //
        make_unique<WriteElectricalMeasurementRmsVoltageSwellPeriod>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriod>(), //
        make_unique<ReadElectricalMeasurementAcVoltageMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcVoltageMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcVoltageDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcVoltageDivisor>(), //
        make_unique<ReadElectricalMeasurementAcCurrentMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcCurrentMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcCurrentDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcCurrentDivisor>(), //
        make_unique<ReadElectricalMeasurementAcPowerMultiplier>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcPowerMultiplier>(), //
        make_unique<ReadElectricalMeasurementAcPowerDivisor>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcPowerDivisor>(), //
        make_unique<ReadElectricalMeasurementOverloadAlarmsMask>(), //
        make_unique<WriteElectricalMeasurementOverloadAlarmsMask>(), //
        make_unique<SubscribeAttributeElectricalMeasurementOverloadAlarmsMask>(), //
        make_unique<ReadElectricalMeasurementVoltageOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementVoltageOverload>(), //
        make_unique<ReadElectricalMeasurementCurrentOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementCurrentOverload>(), //
        make_unique<ReadElectricalMeasurementAcOverloadAlarmsMask>(), //
        make_unique<WriteElectricalMeasurementAcOverloadAlarmsMask>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcOverloadAlarmsMask>(), //
        make_unique<ReadElectricalMeasurementAcVoltageOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcVoltageOverload>(), //
        make_unique<ReadElectricalMeasurementAcCurrentOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcCurrentOverload>(), //
        make_unique<ReadElectricalMeasurementAcActivePowerOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcActivePowerOverload>(), //
        make_unique<ReadElectricalMeasurementAcReactivePowerOverload>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcReactivePowerOverload>(), //
        make_unique<ReadElectricalMeasurementAverageRmsOverVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsOverVoltage>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltage>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltage>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSag>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSag>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwell>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwell>(), //
        make_unique<ReadElectricalMeasurementLineCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementLineCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementActiveCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActiveCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementReactiveCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltagePhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltagePhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMinPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMaxPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMinPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMaxPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseB>(), //
        make_unique<ReadElectricalMeasurementActivePowerPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerPhaseB>(), //
        make_unique<ReadElectricalMeasurementActivePowerMinPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMinPhaseB>(), //
        make_unique<ReadElectricalMeasurementActivePowerMaxPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseB>(), //
        make_unique<ReadElectricalMeasurementReactivePowerPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactivePowerPhaseB>(), //
        make_unique<ReadElectricalMeasurementApparentPowerPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementApparentPowerPhaseB>(), //
        make_unique<ReadElectricalMeasurementPowerFactorPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerFactorPhaseB>(), //
        make_unique<ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseB>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSagPeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseB>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseB>(), //
        make_unique<ReadElectricalMeasurementLineCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementLineCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementActiveCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActiveCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementReactiveCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactiveCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltagePhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltagePhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMinPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMinPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageMaxPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageMaxPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMinPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMinPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsCurrentMaxPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsCurrentMaxPhaseC>(), //
        make_unique<ReadElectricalMeasurementActivePowerPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerPhaseC>(), //
        make_unique<ReadElectricalMeasurementActivePowerMinPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMinPhaseC>(), //
        make_unique<ReadElectricalMeasurementActivePowerMaxPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementActivePowerMaxPhaseC>(), //
        make_unique<ReadElectricalMeasurementReactivePowerPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementReactivePowerPhaseC>(), //
        make_unique<ReadElectricalMeasurementApparentPowerPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementApparentPowerPhaseC>(), //
        make_unique<ReadElectricalMeasurementPowerFactorPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementPowerFactorPhaseC>(), //
        make_unique<ReadElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsVoltageMeasurementPeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementAverageRmsOverVoltageCounterPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsOverVoltageCounterPhaseC>(), //
        make_unique<ReadElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAverageRmsUnderVoltageCounterPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeOverVoltagePeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsExtremeUnderVoltagePeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSagPeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSagPeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementRmsVoltageSwellPeriodPhaseC>(), //
        make_unique<SubscribeAttributeElectricalMeasurementRmsVoltageSwellPeriodPhaseC>(), //
        make_unique<ReadElectricalMeasurementGeneratedCommandList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementGeneratedCommandList>(), //
        make_unique<ReadElectricalMeasurementAcceptedCommandList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAcceptedCommandList>(), //
        make_unique<ReadElectricalMeasurementAttributeList>(), //
        make_unique<SubscribeAttributeElectricalMeasurementAttributeList>(), //
        make_unique<ReadElectricalMeasurementFeatureMap>(), //
        make_unique<SubscribeAttributeElectricalMeasurementFeatureMap>(), //
        make_unique<ReadElectricalMeasurementClusterRevision>(), //
        make_unique<SubscribeAttributeElectricalMeasurementClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}
void registerClusterTestCluster(Commands & commands)
{
    using namespace chip::app::Clusters::TestCluster;

    const char * clusterName = "TestCluster";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(Id), //
        make_unique<TestClusterTest>(), //
        make_unique<TestClusterTestNotHandled>(), //
        make_unique<TestClusterTestSpecific>(), //
        make_unique<TestClusterTestUnknownCommand>(), //
        make_unique<TestClusterTestAddArguments>(), //
        make_unique<TestClusterTestSimpleArgumentRequest>(), //
        make_unique<TestClusterTestStructArrayArgumentRequest>(), //
        make_unique<TestClusterTestStructArgumentRequest>(), //
        make_unique<TestClusterTestNestedStructArgumentRequest>(), //
        make_unique<TestClusterTestListStructArgumentRequest>(), //
        make_unique<TestClusterTestListInt8UArgumentRequest>(), //
        make_unique<TestClusterTestNestedStructListArgumentRequest>(), //
        make_unique<TestClusterTestListNestedStructListArgumentRequest>(), //
        make_unique<TestClusterTestListInt8UReverseRequest>(), //
        make_unique<TestClusterTestEnumsRequest>(), //
        make_unique<TestClusterTestNullableOptionalRequest>(), //
        make_unique<TestClusterTestComplexNullableOptionalRequest>(), //
        make_unique<TestClusterSimpleStructEchoRequest>(), //
        make_unique<TestClusterTimedInvokeRequest>(), //
        make_unique<TestClusterTestSimpleOptionalArgumentRequest>(), //
        make_unique<TestClusterTestEmitTestEventRequest>(), //
        make_unique<TestClusterTestEmitTestFabricScopedEventRequest>(), //
        make_unique<ReadAttribute>(Id), //
        make_unique<ReadTestClusterBoolean>(), //
        make_unique<WriteAttribute>(Id), //
        make_unique<WriteTestClusterBoolean>(), //
        make_unique<SubscribeAttribute>(Id), //
        make_unique<SubscribeAttributeTestClusterBoolean>(), //
        make_unique<ReadTestClusterBitmap8>(), //
        make_unique<WriteTestClusterBitmap8>(), //
        make_unique<SubscribeAttributeTestClusterBitmap8>(), //
        make_unique<ReadTestClusterBitmap16>(), //
        make_unique<WriteTestClusterBitmap16>(), //
        make_unique<SubscribeAttributeTestClusterBitmap16>(), //
        make_unique<ReadTestClusterBitmap32>(), //
        make_unique<WriteTestClusterBitmap32>(), //
        make_unique<SubscribeAttributeTestClusterBitmap32>(), //
        make_unique<ReadTestClusterBitmap64>(), //
        make_unique<WriteTestClusterBitmap64>(), //
        make_unique<SubscribeAttributeTestClusterBitmap64>(), //
        make_unique<ReadTestClusterInt8u>(), //
        make_unique<WriteTestClusterInt8u>(), //
        make_unique<SubscribeAttributeTestClusterInt8u>(), //
        make_unique<ReadTestClusterInt16u>(), //
        make_unique<WriteTestClusterInt16u>(), //
        make_unique<SubscribeAttributeTestClusterInt16u>(), //
        make_unique<ReadTestClusterInt24u>(), //
        make_unique<WriteTestClusterInt24u>(), //
        make_unique<SubscribeAttributeTestClusterInt24u>(), //
        make_unique<ReadTestClusterInt32u>(), //
        make_unique<WriteTestClusterInt32u>(), //
        make_unique<SubscribeAttributeTestClusterInt32u>(), //
        make_unique<ReadTestClusterInt40u>(), //
        make_unique<WriteTestClusterInt40u>(), //
        make_unique<SubscribeAttributeTestClusterInt40u>(), //
        make_unique<ReadTestClusterInt48u>(), //
        make_unique<WriteTestClusterInt48u>(), //
        make_unique<SubscribeAttributeTestClusterInt48u>(), //
        make_unique<ReadTestClusterInt56u>(), //
        make_unique<WriteTestClusterInt56u>(), //
        make_unique<SubscribeAttributeTestClusterInt56u>(), //
        make_unique<ReadTestClusterInt64u>(), //
        make_unique<WriteTestClusterInt64u>(), //
        make_unique<SubscribeAttributeTestClusterInt64u>(), //
        make_unique<ReadTestClusterInt8s>(), //
        make_unique<WriteTestClusterInt8s>(), //
        make_unique<SubscribeAttributeTestClusterInt8s>(), //
        make_unique<ReadTestClusterInt16s>(), //
        make_unique<WriteTestClusterInt16s>(), //
        make_unique<SubscribeAttributeTestClusterInt16s>(), //
        make_unique<ReadTestClusterInt24s>(), //
        make_unique<WriteTestClusterInt24s>(), //
        make_unique<SubscribeAttributeTestClusterInt24s>(), //
        make_unique<ReadTestClusterInt32s>(), //
        make_unique<WriteTestClusterInt32s>(), //
        make_unique<SubscribeAttributeTestClusterInt32s>(), //
        make_unique<ReadTestClusterInt40s>(), //
        make_unique<WriteTestClusterInt40s>(), //
        make_unique<SubscribeAttributeTestClusterInt40s>(), //
        make_unique<ReadTestClusterInt48s>(), //
        make_unique<WriteTestClusterInt48s>(), //
        make_unique<SubscribeAttributeTestClusterInt48s>(), //
        make_unique<ReadTestClusterInt56s>(), //
        make_unique<WriteTestClusterInt56s>(), //
        make_unique<SubscribeAttributeTestClusterInt56s>(), //
        make_unique<ReadTestClusterInt64s>(), //
        make_unique<WriteTestClusterInt64s>(), //
        make_unique<SubscribeAttributeTestClusterInt64s>(), //
        make_unique<ReadTestClusterEnum8>(), //
        make_unique<WriteTestClusterEnum8>(), //
        make_unique<SubscribeAttributeTestClusterEnum8>(), //
        make_unique<ReadTestClusterEnum16>(), //
        make_unique<WriteTestClusterEnum16>(), //
        make_unique<SubscribeAttributeTestClusterEnum16>(), //
        make_unique<ReadTestClusterFloatSingle>(), //
        make_unique<WriteTestClusterFloatSingle>(), //
        make_unique<SubscribeAttributeTestClusterFloatSingle>(), //
        make_unique<ReadTestClusterFloatDouble>(), //
        make_unique<WriteTestClusterFloatDouble>(), //
        make_unique<SubscribeAttributeTestClusterFloatDouble>(), //
        make_unique<ReadTestClusterOctetString>(), //
        make_unique<WriteTestClusterOctetString>(), //
        make_unique<SubscribeAttributeTestClusterOctetString>(), //
        make_unique<ReadTestClusterListInt8u>(), //
        make_unique<WriteTestClusterListInt8u>(), //
        make_unique<SubscribeAttributeTestClusterListInt8u>(), //
        make_unique<ReadTestClusterListOctetString>(), //
        make_unique<WriteTestClusterListOctetString>(), //
        make_unique<SubscribeAttributeTestClusterListOctetString>(), //
        make_unique<ReadTestClusterListStructOctetString>(), //
        make_unique<WriteTestClusterListStructOctetString>(), //
        make_unique<SubscribeAttributeTestClusterListStructOctetString>(), //
        make_unique<ReadTestClusterLongOctetString>(), //
        make_unique<WriteTestClusterLongOctetString>(), //
        make_unique<SubscribeAttributeTestClusterLongOctetString>(), //
        make_unique<ReadTestClusterCharString>(), //
        make_unique<WriteTestClusterCharString>(), //
        make_unique<SubscribeAttributeTestClusterCharString>(), //
        make_unique<ReadTestClusterLongCharString>(), //
        make_unique<WriteTestClusterLongCharString>(), //
        make_unique<SubscribeAttributeTestClusterLongCharString>(), //
        make_unique<ReadTestClusterEpochUs>(), //
        make_unique<WriteTestClusterEpochUs>(), //
        make_unique<SubscribeAttributeTestClusterEpochUs>(), //
        make_unique<ReadTestClusterEpochS>(), //
        make_unique<WriteTestClusterEpochS>(), //
        make_unique<SubscribeAttributeTestClusterEpochS>(), //
        make_unique<ReadTestClusterVendorId>(), //
        make_unique<WriteTestClusterVendorId>(), //
        make_unique<SubscribeAttributeTestClusterVendorId>(), //
        make_unique<ReadTestClusterListNullablesAndOptionalsStruct>(), //
        make_unique<WriteTestClusterListNullablesAndOptionalsStruct>(), //
        make_unique<SubscribeAttributeTestClusterListNullablesAndOptionalsStruct>(), //
        make_unique<ReadTestClusterEnumAttr>(), //
        make_unique<WriteTestClusterEnumAttr>(), //
        make_unique<SubscribeAttributeTestClusterEnumAttr>(), //
        make_unique<ReadTestClusterStructAttr>(), //
        make_unique<WriteTestClusterStructAttr>(), //
        make_unique<SubscribeAttributeTestClusterStructAttr>(), //
        make_unique<ReadTestClusterRangeRestrictedInt8u>(), //
        make_unique<WriteTestClusterRangeRestrictedInt8u>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt8u>(), //
        make_unique<ReadTestClusterRangeRestrictedInt8s>(), //
        make_unique<WriteTestClusterRangeRestrictedInt8s>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt8s>(), //
        make_unique<ReadTestClusterRangeRestrictedInt16u>(), //
        make_unique<WriteTestClusterRangeRestrictedInt16u>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt16u>(), //
        make_unique<ReadTestClusterRangeRestrictedInt16s>(), //
        make_unique<WriteTestClusterRangeRestrictedInt16s>(), //
        make_unique<SubscribeAttributeTestClusterRangeRestrictedInt16s>(), //
        make_unique<ReadTestClusterListLongOctetString>(), //
        make_unique<WriteTestClusterListLongOctetString>(), //
        make_unique<SubscribeAttributeTestClusterListLongOctetString>(), //
        make_unique<ReadTestClusterListFabricScoped>(), //
        make_unique<WriteTestClusterListFabricScoped>(), //
        make_unique<SubscribeAttributeTestClusterListFabricScoped>(), //
        make_unique<ReadTestClusterTimedWriteBoolean>(), //
        make_unique<WriteTestClusterTimedWriteBoolean>(), //
        make_unique<SubscribeAttributeTestClusterTimedWriteBoolean>(), //
        make_unique<ReadTestClusterGeneralErrorBoolean>(), //
        make_unique<WriteTestClusterGeneralErrorBoolean>(), //
        make_unique<SubscribeAttributeTestClusterGeneralErrorBoolean>(), //
        make_unique<ReadTestClusterClusterErrorBoolean>(), //
        make_unique<WriteTestClusterClusterErrorBoolean>(), //
        make_unique<SubscribeAttributeTestClusterClusterErrorBoolean>(), //
        make_unique<ReadTestClusterUnsupported>(), //
        make_unique<WriteTestClusterUnsupported>(), //
        make_unique<SubscribeAttributeTestClusterUnsupported>(), //
        make_unique<ReadTestClusterNullableBoolean>(), //
        make_unique<WriteTestClusterNullableBoolean>(), //
        make_unique<SubscribeAttributeTestClusterNullableBoolean>(), //
        make_unique<ReadTestClusterNullableBitmap8>(), //
        make_unique<WriteTestClusterNullableBitmap8>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap8>(), //
        make_unique<ReadTestClusterNullableBitmap16>(), //
        make_unique<WriteTestClusterNullableBitmap16>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap16>(), //
        make_unique<ReadTestClusterNullableBitmap32>(), //
        make_unique<WriteTestClusterNullableBitmap32>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap32>(), //
        make_unique<ReadTestClusterNullableBitmap64>(), //
        make_unique<WriteTestClusterNullableBitmap64>(), //
        make_unique<SubscribeAttributeTestClusterNullableBitmap64>(), //
        make_unique<ReadTestClusterNullableInt8u>(), //
        make_unique<WriteTestClusterNullableInt8u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt8u>(), //
        make_unique<ReadTestClusterNullableInt16u>(), //
        make_unique<WriteTestClusterNullableInt16u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt16u>(), //
        make_unique<ReadTestClusterNullableInt24u>(), //
        make_unique<WriteTestClusterNullableInt24u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt24u>(), //
        make_unique<ReadTestClusterNullableInt32u>(), //
        make_unique<WriteTestClusterNullableInt32u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt32u>(), //
        make_unique<ReadTestClusterNullableInt40u>(), //
        make_unique<WriteTestClusterNullableInt40u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt40u>(), //
        make_unique<ReadTestClusterNullableInt48u>(), //
        make_unique<WriteTestClusterNullableInt48u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt48u>(), //
        make_unique<ReadTestClusterNullableInt56u>(), //
        make_unique<WriteTestClusterNullableInt56u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt56u>(), //
        make_unique<ReadTestClusterNullableInt64u>(), //
        make_unique<WriteTestClusterNullableInt64u>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt64u>(), //
        make_unique<ReadTestClusterNullableInt8s>(), //
        make_unique<WriteTestClusterNullableInt8s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt8s>(), //
        make_unique<ReadTestClusterNullableInt16s>(), //
        make_unique<WriteTestClusterNullableInt16s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt16s>(), //
        make_unique<ReadTestClusterNullableInt24s>(), //
        make_unique<WriteTestClusterNullableInt24s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt24s>(), //
        make_unique<ReadTestClusterNullableInt32s>(), //
        make_unique<WriteTestClusterNullableInt32s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt32s>(), //
        make_unique<ReadTestClusterNullableInt40s>(), //
        make_unique<WriteTestClusterNullableInt40s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt40s>(), //
        make_unique<ReadTestClusterNullableInt48s>(), //
        make_unique<WriteTestClusterNullableInt48s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt48s>(), //
        make_unique<ReadTestClusterNullableInt56s>(), //
        make_unique<WriteTestClusterNullableInt56s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt56s>(), //
        make_unique<ReadTestClusterNullableInt64s>(), //
        make_unique<WriteTestClusterNullableInt64s>(), //
        make_unique<SubscribeAttributeTestClusterNullableInt64s>(), //
        make_unique<ReadTestClusterNullableEnum8>(), //
        make_unique<WriteTestClusterNullableEnum8>(), //
        make_unique<SubscribeAttributeTestClusterNullableEnum8>(), //
        make_unique<ReadTestClusterNullableEnum16>(), //
        make_unique<WriteTestClusterNullableEnum16>(), //
        make_unique<SubscribeAttributeTestClusterNullableEnum16>(), //
        make_unique<ReadTestClusterNullableFloatSingle>(), //
        make_unique<WriteTestClusterNullableFloatSingle>(), //
        make_unique<SubscribeAttributeTestClusterNullableFloatSingle>(), //
        make_unique<ReadTestClusterNullableFloatDouble>(), //
        make_unique<WriteTestClusterNullableFloatDouble>(), //
        make_unique<SubscribeAttributeTestClusterNullableFloatDouble>(), //
        make_unique<ReadTestClusterNullableOctetString>(), //
        make_unique<WriteTestClusterNullableOctetString>(), //
        make_unique<SubscribeAttributeTestClusterNullableOctetString>(), //
        make_unique<ReadTestClusterNullableCharString>(), //
        make_unique<WriteTestClusterNullableCharString>(), //
        make_unique<SubscribeAttributeTestClusterNullableCharString>(), //
        make_unique<ReadTestClusterNullableEnumAttr>(), //
        make_unique<WriteTestClusterNullableEnumAttr>(), //
        make_unique<SubscribeAttributeTestClusterNullableEnumAttr>(), //
        make_unique<ReadTestClusterNullableStruct>(), //
        make_unique<WriteTestClusterNullableStruct>(), //
        make_unique<SubscribeAttributeTestClusterNullableStruct>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt8u>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt8u>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt8u>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt8s>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt8s>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt8s>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt16u>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt16u>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt16u>(), //
        make_unique<ReadTestClusterNullableRangeRestrictedInt16s>(), //
        make_unique<WriteTestClusterNullableRangeRestrictedInt16s>(), //
        make_unique<SubscribeAttributeTestClusterNullableRangeRestrictedInt16s>(), //
        make_unique<ReadTestClusterWriteOnlyInt8u>(), //
        make_unique<WriteTestClusterWriteOnlyInt8u>(), //
        make_unique<SubscribeAttributeTestClusterWriteOnlyInt8u>(), //
        make_unique<ReadTestClusterGeneratedCommandList>(), //
        make_unique<SubscribeAttributeTestClusterGeneratedCommandList>(), //
        make_unique<ReadTestClusterAcceptedCommandList>(), //
        make_unique<SubscribeAttributeTestClusterAcceptedCommandList>(), //
        make_unique<ReadTestClusterAttributeList>(), //
        make_unique<SubscribeAttributeTestClusterAttributeList>(), //
        make_unique<ReadTestClusterFeatureMap>(), //
        make_unique<SubscribeAttributeTestClusterFeatureMap>(), //
        make_unique<ReadTestClusterClusterRevision>(), //
        make_unique<SubscribeAttributeTestClusterClusterRevision>(), //
    };

    commands.Register(clusterName, clusterCommands);
}

void registerClusterAny(Commands & commands)
{
    const char * clusterName = "Any";

    commands_list clusterCommands = {
        make_unique<ClusterCommand>(), //
        make_unique<ReadAttribute>(), //
        make_unique<WriteAttribute>(), //
        make_unique<SubscribeAttribute>(), //
        make_unique<SubscribeEvent>(), //
    };

    commands.Register(clusterName, clusterCommands);
}

void registerClusters(Commands & commands)
{
    registerClusterAny(commands);
    registerClusterIdentify(commands);
    registerClusterGroups(commands);
    registerClusterScenes(commands);
    registerClusterOnOff(commands);
    registerClusterOnOffSwitchConfiguration(commands);
    registerClusterLevelControl(commands);
    registerClusterBinaryInputBasic(commands);
    registerClusterDescriptor(commands);
    registerClusterBinding(commands);
    registerClusterAccessControl(commands);
    registerClusterActions(commands);
    registerClusterBasic(commands);
    registerClusterOtaSoftwareUpdateProvider(commands);
    registerClusterOtaSoftwareUpdateRequestor(commands);
    registerClusterLocalizationConfiguration(commands);
    registerClusterTimeFormatLocalization(commands);
    registerClusterUnitLocalization(commands);
    registerClusterPowerSourceConfiguration(commands);
    registerClusterPowerSource(commands);
    registerClusterGeneralCommissioning(commands);
    registerClusterNetworkCommissioning(commands);
    registerClusterDiagnosticLogs(commands);
    registerClusterGeneralDiagnostics(commands);
    registerClusterSoftwareDiagnostics(commands);
    registerClusterThreadNetworkDiagnostics(commands);
    registerClusterWiFiNetworkDiagnostics(commands);
    registerClusterEthernetNetworkDiagnostics(commands);
    registerClusterBridgedDeviceBasic(commands);
    registerClusterSwitch(commands);
    registerClusterAdministratorCommissioning(commands);
    registerClusterOperationalCredentials(commands);
    registerClusterGroupKeyManagement(commands);
    registerClusterFixedLabel(commands);
    registerClusterUserLabel(commands);
    registerClusterBooleanState(commands);
    registerClusterModeSelect(commands);
    registerClusterDoorLock(commands);
    registerClusterWindowCovering(commands);
    registerClusterBarrierControl(commands);
    registerClusterPumpConfigurationAndControl(commands);
    registerClusterThermostat(commands);
    registerClusterFanControl(commands);
    registerClusterThermostatUserInterfaceConfiguration(commands);
    registerClusterColorControl(commands);
    registerClusterBallastConfiguration(commands);
    registerClusterIlluminanceMeasurement(commands);
    registerClusterTemperatureMeasurement(commands);
    registerClusterPressureMeasurement(commands);
    registerClusterFlowMeasurement(commands);
    registerClusterRelativeHumidityMeasurement(commands);
    registerClusterOccupancySensing(commands);
    registerClusterWakeOnLan(commands);
    registerClusterChannel(commands);
    registerClusterTargetNavigator(commands);
    registerClusterMediaPlayback(commands);
    registerClusterMediaInput(commands);
    registerClusterLowPower(commands);
    registerClusterKeypadInput(commands);
    registerClusterContentLauncher(commands);
    registerClusterAudioOutput(commands);
    registerClusterApplicationLauncher(commands);
    registerClusterApplicationBasic(commands);
    registerClusterAccountLogin(commands);
    registerClusterElectricalMeasurement(commands);
    registerClusterTestCluster(commands);
}
